svg重编译,支持石化自绘的svg文件转视图

This commit is contained in:
jiayulong 2025-12-10 14:45:07 +08:00
parent fcce4f565a
commit 235c1d7fff
37 changed files with 13138 additions and 22 deletions

View File

@ -161,14 +161,14 @@ private:
// 左边界矩形控制点
mLeftHandle->topLeft->setParentAnchor(mRect->topLeft);
mLeftHandle->bottomRight->setParentAnchor(mRect->topRight);//(mRect->bottomLeft);
mLeftHandle->topLeft->setCoords(-5, 5); // 矩形大小
mLeftHandle->bottomRight->setCoords(5, -5); // 矩形大小
mLeftHandle->topLeft->setCoords(-0.5, 0.5); // 矩形大小
mLeftHandle->bottomRight->setCoords(0.5, -0.5); // 矩形大小
// 右边界矩形控制点
mRightHandle->topLeft->setParentAnchor(mRect->bottomLeft);
mRightHandle->bottomRight->setParentAnchor(mRect->bottomRight);
mRightHandle->topLeft->setCoords(-5, 5); // 矩形大小
mRightHandle->bottomRight->setCoords(5, -5); // 矩形大小
mRightHandle->topLeft->setCoords(-0.5, 0.5); // 矩形大小
mRightHandle->bottomRight->setCoords(0.5, -0.5); // 矩形大小
}

View File

@ -36,7 +36,56 @@ public:
// mPlot->removeItem(mRightHandle);
}
}
void DrawSVGNormal(QPainter* painter,QString svgFileName,QRectF borderRect,bool IsWellSectonHorizonLayout)
{
QString svg=svgFileName;
QRectF boundingRect = painter->transform().mapRect(borderRect);
painter->save();
QTransform transform;
transform.reset();
if (!IsWellSectonHorizonLayout)
{
painter->setWorldTransform(transform);
}
else
{
}
QPixmap tiledmap(svg);
QRect border(boundingRect.left(),boundingRect.top(),boundingRect.width(),boundingRect.height());
painter->drawPixmap(border,tiledmap);
painter->restore();
}
//拉伸
void DrawSVGSteched(QPainter* painter,QString svgFileName,QRectF borderRect,bool IsWellSectonHorizonLayout)
{
QString svg;
QSvgRenderer m_SvgRenderer;
svg=svgFileName;
m_SvgRenderer.load(svg);
m_SvgRenderer.render(painter,borderRect);
}
//平铺
void DrawSVGTiled(QPainter* painter,QString svgFileName,QRectF borderRect,bool IsWellSectonHorizonLayout)
{
QString svg=svgFileName;
QRectF boundingRect = painter->transform().mapRect(borderRect);
painter->save();
QTransform transform;
transform.reset();
if (!IsWellSectonHorizonLayout)
{
painter->setWorldTransform(transform);
}
else
{
}
QPixmap tiledmap(svg);
painter->drawTiledPixmap(boundingRect,tiledmap);
painter->restore();
}
//设置最小宽度
void setMinWidth(double minWidth){
mMinWidth = minWidth;
@ -50,25 +99,54 @@ public:
}
//设置解释结论
void setResult(QString result){
m_Result = result;
void setResult(QString filePath){
m_Result = filePath;
//
QString strLast = result.right(4);
QString strLast = filePath.right(4);
if(strLast.toLower()==".svg")
{
QSvgRenderer* svgRender = new QSvgRenderer();
svgRender->load(result);
//
QPixmap* pixmap = new QPixmap(10, 10);
pixmap->fill(Qt::transparent);//设置背景透明
QPainter p(pixmap);
svgRender->render(&p);
//
mPixmap->setPixmap(*pixmap); // 设置图片
QString path,filename;
GetWellNameAndPath(filePath, filename, path);
QString basename = filename.left(filename.size()-4);
QString val=filePath;
QImage image(320,160,QImage::Format_RGB32);
QPainter painter(&image);
QRectF fillRect(0,0,320,160);
painter.fillRect(fillRect,Qt::white);
//拉伸
DrawSVGSteched(&painter,filePath,fillRect,0);
//平铺
//DrawSVGTiled(&painter,filePath,fillRect,0);
//正常
//DrawSVGNormal(&painter,filePath,fillRect,0);
val=GetImagePath()+"TempNew";
QDir ss;
if(!ss.exists(val)) {
ss.mkdir(val);
}
val+=QDir::separator();
val+=basename+".png";
image.save(val);
//
mPixmap->setPixmap(QPixmap(val)); // 设置图片
// QSvgRenderer* svgRender = new QSvgRenderer();
// svgRender->load(result);
// //
// QPixmap* pixmap = new QPixmap(10, 10);
// pixmap->fill(Qt::transparent);//设置背景透明
// QPainter p(pixmap);
// svgRender->render(&p);
// //
// mPixmap->setPixmap(*pixmap); // 设置图片
}
else
{
mPixmap->setPixmap(QPixmap(result)); // 设置图片
mPixmap->setPixmap(QPixmap(filePath)); // 设置图片
}
@ -197,14 +275,14 @@ private:
// 左边界矩形控制点
mLeftHandle->topLeft->setParentAnchor(mRect->topLeft);
mLeftHandle->bottomRight->setParentAnchor(mRect->topRight);//(mRect->bottomLeft);
mLeftHandle->topLeft->setCoords(-5, 5); // 矩形大小
mLeftHandle->bottomRight->setCoords(5, -5); // 矩形大小
mLeftHandle->topLeft->setCoords(-0.5, 0.5); // 矩形大小
mLeftHandle->bottomRight->setCoords(0.5, -0.5); // 矩形大小
// 右边界矩形控制点
mRightHandle->topLeft->setParentAnchor(mRect->bottomLeft);
mRightHandle->bottomRight->setParentAnchor(mRect->bottomRight);
mRightHandle->topLeft->setCoords(-5, 5); // 矩形大小
mRightHandle->bottomRight->setCoords(5, -5); // 矩形大小
mRightHandle->topLeft->setCoords(-0.5, 0.5); // 矩形大小
mRightHandle->bottomRight->setCoords(0.5, -0.5); // 矩形大小
// if(m_upDraggableResult)
// {

22
svg/XSVG_LICENSE.txt Normal file
View File

@ -0,0 +1,22 @@
Copyright 2002 USC/Information Sciences Institute
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without
fee, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice
appear in supporting documentation, and that the name of
Information Sciences Institute not be used in advertising or
publicity pertaining to distribution of the software without
specific, written prior permission. Information Sciences Institute
makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied
warranty.
INFORMATION SCIENCES INSTITUTE DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INFORMATION SCIENCES
INSTITUTE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

49
svg/doc/qtsvg.qdocconf Normal file
View File

@ -0,0 +1,49 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtSvg
description = Qt SVG Reference Documentation
version = $QT_VERSION
qhp.projects = QtSvg
qhp.QtSvg.file = qtsvg.qhp
qhp.QtSvg.namespace = org.qt-project.qtsvg.$QT_VERSION_TAG
qhp.QtSvg.virtualFolder = qtsvg
qhp.QtSvg.indexTitle = Qt SVG
qhp.QtSvg.indexRoot =
qhp.QtSvg.filterAttributes = qtsvg $QT_VERSION qtrefdoc
qhp.QtSvg.customFilters.Qt.name = QtSvg $QT_VERSION
qhp.QtSvg.customFilters.Qt.filterAttributes = qtsvg $QT_VERSION
qhp.QtSvg.subprojects = classes
qhp.QtSvg.subprojects.classes.title = C++ Classes
qhp.QtSvg.subprojects.classes.indexTitle = Qt SVG C++ Classes
qhp.QtSvg.subprojects.classes.selectors = class fake:headerfile
qhp.QtSvg.subprojects.classes.sortPages = true
depends += qtcore \
qtwidgets \
qtgui \
qtdesigner \
qtdoc \
qmake
tagfile = ../../../doc/qtsvg/qtsvg.tags
headerdirs += .. \
../../plugins/imageformats \
../../plugins/iconengines
sourcedirs += .. \
../../plugins/imageformats \
../../plugins/iconengines
exampledirs += ../../../examples/svg \
snippets/
examplesinstallpath = svg
imagedirs += images
navigation.landingpage = "Qt SVG"
navigation.cppclassespage = "Qt SVG C++ Classes"

View File

@ -0,0 +1,53 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//! [0]
#include <QtSvg>
//! [0]

View File

@ -0,0 +1,53 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#! [1]
QT += svg
#! [1]

View File

@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//! [0]
QSvgRenderer *renderer = new QSvgRenderer(QLatin1String("SvgCardDeck.svg"));
QGraphicsSvgItem *black = new QGraphicsSvgItem();
QGraphicsSvgItem *red = new QGraphicsSvgItem();
black->setSharedRenderer(renderer);
black->setElementId(QLatin1String("black_joker"));
red->setSharedRenderer(renderer);
red->setElementId(QLatin1String("red_joker"));
//! [0]

View File

@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt SVG module.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\title Qt SVG
\page qtsvg-index.html
\brief Qt SVG provides functionality for handling SVG images.
Scalable Vector Graphics (SVG) is an XML-based language for
describing two-dimensional vector graphics. Qt provides classes
for rendering and displaying SVG drawings in widgets and on other
paint devices.
\section1 Getting Started
Qt SVG provides classes for rendering SVG files. To include the definitions
of the module's classes, use the following directive:
\snippet doc_src_qtsvg.cpp 0
To link against the module, add this line to your \l qmake \c
.pro file:
\snippet doc_src_qtsvg.pro 1
\section1 Licenses and Attributions
Qt SVG is available under commercial licenses from \l{The Qt Company}.
In addition, it is available under the
\l{GNU Lesser General Public License, version 3}, or
the \l{GNU General Public License, version 2}.
See \l{Qt Licensing} for further details.
Furthermore Qt SVG contains third party
code under following permissive licenses:
\generatelist{groupsbymodule attributions-qtsvg}
\section1 Articles
\list
\li \l{Rendering SVG Files} contains information about how to
render SVG files
\endlist
\section1 References
\list
\li \l{Qt SVG C++ Classes}
\endlist
Qt SVG comes with the following examples:
\list
\li \l{SVG Generator Example}
\li \l{SVG Viewer Example}
\endlist
*/

41
svg/doc/src/qtsvg.qdoc Normal file
View File

@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt SVG module.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\module QtSvg
\title Qt SVG C++ Classes
\ingroup modules
\qtvariable svg
\brief The Qt SVG module provides functionality for handling SVG images.
Scalable Vector Graphics (SVG) is an XML-based language for
describing two-dimensional vector graphics. Qt provides classes
for rendering and displaying SVG drawings in widgets and on other
paint devices. See the class descriptions for further details.
*/

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt SVG module.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page svgrendering.html
\title Rendering SVG Files
\brief Rendering SVG files with the Qt SVG module
Qt SVG provides classes for rendering SVG files. To include the definitions
of the module's classes, use the following directive:
\snippet doc_src_qtsvg.cpp 0
To link against the module, add this line to your \l qmake \c
.pro file:
\snippet doc_src_qtsvg.pro 1
\section1 Rendering SVG Files
Scalable Vector Graphics (SVG) is a language for describing two-dimensional
graphics and graphical applications in XML. SVG 1.1 is a W3C Recommendation
and forms the core of the current SVG developments in Qt. SVG 1.2 is the
specification currently being developed by the \l{SVG Working Group}, and it
is \l{http://www.w3.org/TR/SVG12/}{available in draft form}. The \l{Mobile
SVG Profiles} (SVG Basic and SVG Tiny) are aimed at resource-limited devices
and are part of the 3GPP platform for third generation mobile phones. You
can read more about SVG at \l{About SVG}.
Qt supports the \l{SVG 1.2 Tiny Static Features}{static features} of
\l{http://www.w3.org/TR/SVGMobile12}{SVG 1.2 Tiny}. ECMA scripts and DOM manipulation are currently not
supported.
SVG drawings can be rendered onto any QPaintDevice subclass. This
approach gives developers the flexibility to experiment, in order
to find the best solution for each application.
The easiest way to render SVG files is to construct a QSvgWidget and
load an SVG file using one of the QSvgWidget::load() functions.
QSvgRenderer is the class responsible for rendering SVG files for
QSvgWidget, and it can be used directly to provide SVG support for
custom widgets.
To load an SVG file, construct a QSvgRenderer with a file name or the
contents of a file, or call QSvgRenderer::load() on an existing
renderer. If the SVG file has been loaded successfully the
QSvgRenderer::isValid() will return true.
Once you have loaded the SVG file successfully, you can render it
with the QSvgRenderer::render() function. Note that this scheme allows
you to render SVG files on all paint devices supported by Qt, including
QWidget, QGLWidget, and QImage. See the \l{SVG Viewer Example}{SVG Viewer}
example for more details.
*/

388
svg/qgraphicssvgitem.cpp Normal file
View File

@ -0,0 +1,388 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgraphicssvgitem.h"
#if !defined(QT_NO_GRAPHICSVIEW) && !defined(QT_NO_WIDGETS)
#include "qpainter.h"
#include "qstyleoption.h"
#include "qsvgrenderer.h"
#include "qdebug.h"
#include "private/qobject_p.h"
#include "private/qgraphicsitem_p.h"
QT_BEGIN_NAMESPACE
class QGraphicsSvgItemPrivate : public QGraphicsItemPrivate
{
public:
Q_DECLARE_PUBLIC(QGraphicsSvgItem)
QGraphicsSvgItemPrivate()
: renderer(0), shared(false)
{
}
void init(QGraphicsItem *parent)
{
Q_Q(QGraphicsSvgItem);
q->setParentItem(parent);
renderer = new QSvgRenderer(q);
QObject::connect(renderer, SIGNAL(repaintNeeded()),
q, SLOT(_q_repaintItem()));
q->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
q->setMaximumCacheSize(QSize(1024, 768));
}
void _q_repaintItem()
{
q_func()->update();
}
inline void updateDefaultSize()
{
QRectF bounds;
if (elemId.isEmpty()) {
bounds = QRectF(QPointF(0, 0), renderer->defaultSize());
} else {
bounds = renderer->boundsOnElement(elemId);
}
if (boundingRect.size() != bounds.size()) {
q_func()->prepareGeometryChange();
boundingRect.setSize(bounds.size());
}
}
QSvgRenderer *renderer;
QRectF boundingRect;
bool shared;
QString elemId;
};
/*!
\class QGraphicsSvgItem
\inmodule QtSvg
\ingroup graphicsview-api
\brief The QGraphicsSvgItem class is a QGraphicsItem that can be used to render
the contents of SVG files.
\since 4.2
QGraphicsSvgItem provides a way of rendering SVG files onto QGraphicsView.
QGraphicsSvgItem can be created by passing the SVG file to be rendered to
its constructor or by explicit setting a shared QSvgRenderer on it.
Note that setting QSvgRenderer on a QGraphicsSvgItem doesn't make the item take
ownership of the renderer, therefore if using setSharedRenderer() method one has
to make sure that the lifetime of the QSvgRenderer object will be at least as long
as that of the QGraphicsSvgItem.
QGraphicsSvgItem provides a way of rendering only parts of the SVG files via
the setElementId. If setElementId() method is called, only the SVG element
(and its children) with the passed id will be renderer. This provides a convenient
way of selectively rendering large SVG files that contain a number of discrete
elements. For example the following code renders only jokers from a SVG file
containing a whole card deck:
\snippet src_svg_qgraphicssvgitem.cpp 0
Size of the item can be set via direct manipulation of the items
transformation matrix.
By default the SVG rendering is cached using QGraphicsItem::DeviceCoordinateCache
mode to speedup the display of items. Caching can be disabled by passing
QGraphicsItem::NoCache to the QGraphicsItem::setCacheMode() method.
\sa QSvgWidget, {Qt SVG C++ Classes}, QGraphicsItem, QGraphicsView
*/
/*!
Constructs a new SVG item with the given \a parent.
*/
QGraphicsSvgItem::QGraphicsSvgItem(QGraphicsItem *parent)
: QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0)
{
Q_D(QGraphicsSvgItem);
d->init(parent);
}
/*!
Constructs a new item with the given \a parent and loads the contents of the
SVG file with the specified \a fileName.
*/
QGraphicsSvgItem::QGraphicsSvgItem(const QString &fileName, QGraphicsItem *parent)
: QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0)
{
Q_D(QGraphicsSvgItem);
d->init(parent);
d->renderer->load(fileName);
d->updateDefaultSize();
}
/*!
Returns the currently use QSvgRenderer.
*/
QSvgRenderer *QGraphicsSvgItem::renderer() const
{
return d_func()->renderer;
}
/*!
Returns the bounding rectangle of this item.
*/
QRectF QGraphicsSvgItem::boundingRect() const
{
Q_D(const QGraphicsSvgItem);
return d->boundingRect;
}
/*!
\internal
Highlights \a item as selected.
NOTE: This function is a duplicate of qt_graphicsItem_highlightSelected() in qgraphicsitem.cpp!
*/
static void qt_graphicsItem_highlightSelected(
QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
{
const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
return;
const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
return;
qreal itemPenWidth;
switch (item->type()) {
case QGraphicsEllipseItem::Type:
itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF();
break;
case QGraphicsPathItem::Type:
itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF();
break;
case QGraphicsPolygonItem::Type:
itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF();
break;
case QGraphicsRectItem::Type:
itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF();
break;
case QGraphicsSimpleTextItem::Type:
itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF();
break;
case QGraphicsLineItem::Type:
itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF();
break;
default:
itemPenWidth = 1.0;
}
const qreal pad = itemPenWidth / 2;
const qreal penWidth = 0; // cosmetic pen
const QColor fgcolor = option->palette.windowText().color();
const QColor bgcolor( // ensure good contrast against fgcolor
fgcolor.red() > 127 ? 0 : 255,
fgcolor.green() > 127 ? 0 : 255,
fgcolor.blue() > 127 ? 0 : 255);
painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
}
/*!
\reimp
*/
void QGraphicsSvgItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
// Q_UNUSED(option);
Q_UNUSED(widget);
Q_D(QGraphicsSvgItem);
if (!d->renderer->isValid())
return;
if (d->elemId.isEmpty())
d->renderer->render(painter, d->boundingRect);
else
d->renderer->render(painter, d->elemId, d->boundingRect);
if (option->state & QStyle::State_Selected)
qt_graphicsItem_highlightSelected(this, painter, option);
}
/*!
\reimp
*/
int QGraphicsSvgItem::type() const
{
return Type;
}
/*!
\property QGraphicsSvgItem::maximumCacheSize
\since 4.6
This property holds the maximum size of the device coordinate cache
for this item.
*/
/*!
Sets the maximum device coordinate cache size of the item to \a size.
If the item is cached using QGraphicsItem::DeviceCoordinateCache mode,
caching is bypassed if the extension of the item in device coordinates
is larger than \a size.
The cache corresponds to the QPixmap which is used to cache the
results of the rendering.
Use QPixmapCache::setCacheLimit() to set limitations on the whole cache
and use setMaximumCacheSize() when setting cache size for individual
items.
\sa QGraphicsItem::cacheMode()
*/
void QGraphicsSvgItem::setMaximumCacheSize(const QSize &size)
{
QGraphicsItem::d_ptr->setExtra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize, size);
update();
}
/*!
Returns the current maximum size of the device coordinate cache for this item.
If the item is cached using QGraphicsItem::DeviceCoordinateCache mode,
caching is bypassed if the extension of the item in device coordinates
is larger than the maximum size.
The default maximum cache size is 1024x768.
QPixmapCache::cacheLimit() gives the
cumulative bounds of the whole cache, whereas maximumCacheSize() refers
to a maximum cache size for this particular item.
\sa QGraphicsItem::cacheMode()
*/
QSize QGraphicsSvgItem::maximumCacheSize() const
{
return QGraphicsItem::d_ptr->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
}
/*!
\property QGraphicsSvgItem::elementId
\since 4.6
This property holds the element's XML ID.
*/
/*!
Sets the XML ID of the element to \a id.
*/
void QGraphicsSvgItem::setElementId(const QString &id)
{
Q_D(QGraphicsSvgItem);
d->elemId = id;
d->updateDefaultSize();
update();
}
/*!
Returns the XML ID the element that is currently
being rendered. Returns an empty string if the whole
file is being rendered.
*/
QString QGraphicsSvgItem::elementId() const
{
Q_D(const QGraphicsSvgItem);
return d->elemId;
}
/*!
Sets \a renderer to be a shared QSvgRenderer on the item. By
using this method one can share the same QSvgRenderer on a number
of items. This means that the SVG file will be parsed only once.
QSvgRenderer passed to this method has to exist for as long as
this item is used.
*/
void QGraphicsSvgItem::setSharedRenderer(QSvgRenderer *renderer)
{
Q_D(QGraphicsSvgItem);
if (!d->shared)
delete d->renderer;
d->renderer = renderer;
d->shared = true;
d->updateDefaultSize();
update();
}
/*!
\obsolete
Use QGraphicsItem::setCacheMode() instead. Passing true to this function is equivalent
to QGraphicsItem::setCacheMode(QGraphicsItem::DeviceCoordinateCache).
*/
void QGraphicsSvgItem::setCachingEnabled(bool caching)
{
setCacheMode(caching ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
}
/*!
\obsolete
Use QGraphicsItem::cacheMode() instead.
*/
bool QGraphicsSvgItem::isCachingEnabled() const
{
return cacheMode() != QGraphicsItem::NoCache;
}
QT_END_NAMESPACE
#include "moc_qgraphicssvgitem.cpp"
#endif // QT_NO_WIDGETS

99
svg/qgraphicssvgitem.h Normal file
View File

@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGRAPHICSSVGITEM_H
#define QGRAPHICSSVGITEM_H
#include <QtCore/qglobal.h>
#if !defined(QT_NO_GRAPHICSVIEW) && !defined(QT_NO_WIDGETS)
#include <QtWidgets/qgraphicsitem.h>
#include <QtSvg/qtsvgglobal.h>
QT_BEGIN_NAMESPACE
class QSvgRenderer;
class QGraphicsSvgItemPrivate;
class Q_SVG_EXPORT QGraphicsSvgItem : public QGraphicsObject
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
Q_PROPERTY(QString elementId READ elementId WRITE setElementId)
Q_PROPERTY(QSize maximumCacheSize READ maximumCacheSize WRITE setMaximumCacheSize)
public:
QGraphicsSvgItem(QGraphicsItem *parentItem = nullptr);
QGraphicsSvgItem(const QString &fileName, QGraphicsItem *parentItem = nullptr);
void setSharedRenderer(QSvgRenderer *renderer);
QSvgRenderer *renderer() const;
void setElementId(const QString &id);
QString elementId() const;
void setCachingEnabled(bool);
bool isCachingEnabled() const;
void setMaximumCacheSize(const QSize &size);
QSize maximumCacheSize() const;
QRectF boundingRect() const override;
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr) override;
enum { Type = 13 };
int type() const override;
private:
Q_DISABLE_COPY(QGraphicsSvgItem)
Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsSvgItem)
Q_PRIVATE_SLOT(d_func(), void _q_repaintItem())
};
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW or QT_NO_WIDGETS
#endif // QGRAPHICSSVGITEM_H

136
svg/qsvgfont.cpp Normal file
View File

@ -0,0 +1,136 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgfont_p.h"
#include "qpainter.h"
#include "qpen.h"
#include "qdebug.h"
#include "qpicture.h"
QT_BEGIN_NAMESPACE
QSvgGlyph::QSvgGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX)
: m_unicode(unicode), m_path(path), m_horizAdvX(horizAdvX)
{
}
QSvgFont::QSvgFont(qreal horizAdvX)
: m_horizAdvX(horizAdvX)
{
}
QString QSvgFont::familyName() const
{
return m_familyName;
}
void QSvgFont::addGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX )
{
m_glyphs.insert(unicode, QSvgGlyph(unicode, path,
(horizAdvX==-1)?m_horizAdvX:horizAdvX));
}
void QSvgFont::draw(QPainter *p, const QPointF &point, const QString &str, qreal pixelSize, Qt::Alignment alignment) const
{
p->save();
p->translate(point);
p->scale(pixelSize / m_unitsPerEm, -pixelSize / m_unitsPerEm);
// Calculate the text width to be used for alignment
int textWidth = 0;
QString::const_iterator itr = str.constBegin();
for ( ; itr != str.constEnd(); ++itr) {
QChar unicode = *itr;
if (!m_glyphs.contains(*itr)) {
unicode = 0;
if (!m_glyphs.contains(unicode))
continue;
}
textWidth += static_cast<int>(m_glyphs[unicode].m_horizAdvX);
}
QPoint alignmentOffset(0, 0);
if (alignment == Qt::AlignHCenter) {
alignmentOffset.setX(-textWidth / 2);
} else if (alignment == Qt::AlignRight) {
alignmentOffset.setX(-textWidth);
}
p->translate(alignmentOffset);
// since in SVG the embedded font ain't really a path
// the outline has got to stay untransformed...
qreal penWidth = p->pen().widthF();
penWidth /= (pixelSize/m_unitsPerEm);
QPen pen = p->pen();
pen.setWidthF(penWidth);
p->setPen(pen);
itr = str.constBegin();
for ( ; itr != str.constEnd(); ++itr) {
QChar unicode = *itr;
if (!m_glyphs.contains(*itr)) {
unicode = 0;
if (!m_glyphs.contains(unicode))
continue;
}
p->drawPath(m_glyphs[unicode].m_path);
p->translate(m_glyphs[unicode].m_horizAdvX, 0);
}
p->restore();
}
void QSvgFont::setFamilyName(const QString &name)
{
m_familyName = name;
}
void QSvgFont::setUnitsPerEm(qreal upem)
{
m_unitsPerEm = upem;
}
QT_END_NAMESPACE

98
svg/qsvgfont_p.h Normal file
View File

@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGFONT_P_H
#define QSVGFONT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qpainterpath.h"
#include "qhash.h"
#include "qstring.h"
#include "qsvgstyle_p.h"
#include "qtsvgglobal_p.h"
QT_BEGIN_NAMESPACE
class Q_SVG_PRIVATE_EXPORT QSvgGlyph
{
public:
QSvgGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX);
QSvgGlyph() : m_unicode(0), m_horizAdvX(0) {}
QChar m_unicode;
QPainterPath m_path;
qreal m_horizAdvX;
};
class Q_SVG_PRIVATE_EXPORT QSvgFont : public QSvgRefCounted
{
public:
QSvgFont(qreal horizAdvX);
void setFamilyName(const QString &name);
QString familyName() const;
void setUnitsPerEm(qreal upem);
void addGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX = -1);
void draw(QPainter *p, const QPointF &point, const QString &str, qreal pixelSize, Qt::Alignment alignment) const;
public:
QString m_familyName;
qreal m_unitsPerEm;
qreal m_ascent;
qreal m_descent;
qreal m_horizAdvX;
QHash<QChar, QSvgGlyph> m_glyphs;
};
QT_END_NAMESPACE
#endif // QSVGFONT_P_H

1163
svg/qsvggenerator.cpp Normal file

File diff suppressed because it is too large Load Diff

106
svg/qsvggenerator.h Normal file
View File

@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGGENERATOR_H
#define QSVGGENERATOR_H
#include <QtGui/qpaintdevice.h>
#ifndef QT_NO_SVGGENERATOR
#include <QtCore/qnamespace.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qobjectdefs.h>
#include <QtCore/qscopedpointer.h>
#include <QtSvg/qtsvgglobal.h>
QT_BEGIN_NAMESPACE
class QSvgGeneratorPrivate;
class Q_SVG_EXPORT QSvgGenerator : public QPaintDevice
{
Q_DECLARE_PRIVATE(QSvgGenerator)
Q_PROPERTY(QSize size READ size WRITE setSize)
Q_PROPERTY(QRectF viewBox READ viewBoxF WRITE setViewBox)
Q_PROPERTY(QString title READ title WRITE setTitle)
Q_PROPERTY(QString description READ description WRITE setDescription)
Q_PROPERTY(QString fileName READ fileName WRITE setFileName)
Q_PROPERTY(QIODevice* outputDevice READ outputDevice WRITE setOutputDevice)
Q_PROPERTY(int resolution READ resolution WRITE setResolution)
public:
QSvgGenerator();
~QSvgGenerator();
QString title() const;
void setTitle(const QString &title);
QString description() const;
void setDescription(const QString &description);
QSize size() const;
void setSize(const QSize &size);
QRect viewBox() const;
QRectF viewBoxF() const;
void setViewBox(const QRect &viewBox);
void setViewBox(const QRectF &viewBox);
QString fileName() const;
void setFileName(const QString &fileName);
QIODevice *outputDevice() const;
void setOutputDevice(QIODevice *outputDevice);
void setResolution(int dpi);
int resolution() const;
protected:
QPaintEngine *paintEngine() const override;
int metric(QPaintDevice::PaintDeviceMetric metric) const override;
private:
QScopedPointer<QSvgGeneratorPrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QT_NO_SVGGENERATOR
#endif // QSVGGENERATOR_H

1035
svg/qsvggraphics.cpp Normal file

File diff suppressed because it is too large Load Diff

274
svg/qsvggraphics_p.h Normal file
View File

@ -0,0 +1,274 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGGRAPHICS_P_H
#define QSVGGRAPHICS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsvgnode_p.h"
#include "qtsvgglobal_p.h"
#include "QtGui/qpainterpath.h"
#include "QtGui/qimage.h"
#include "QtGui/qtextlayout.h"
#include "QtGui/qtextoption.h"
#include "QtCore/qstack.h"
QT_BEGIN_NAMESPACE
class QTextCharFormat;
class Q_SVG_PRIVATE_EXPORT QSvgAnimation : public QSvgNode
{
public:
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
};
class Q_SVG_PRIVATE_EXPORT QSvgArc : public QSvgNode
{
public:
QSvgArc(QSvgNode *parent, const QPainterPath &path);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QPainterPath m_path;
};
class Q_SVG_PRIVATE_EXPORT QSvgEllipse : public QSvgNode
{
public:
QSvgEllipse(QSvgNode *parent, const QRectF &rect);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QRectF m_bounds;
};
class Q_SVG_PRIVATE_EXPORT QSvgCircle : public QSvgEllipse
{
public:
QSvgCircle(QSvgNode *parent, const QRectF &rect) : QSvgEllipse(parent, rect) { }
Type type() const override;
};
class Q_SVG_PRIVATE_EXPORT QSvgImage : public QSvgNode
{
public:
QSvgImage(QSvgNode *parent, const QImage &image,
const QRectF &bounds);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QImage m_image;
QRectF m_bounds;
};
class Q_SVG_PRIVATE_EXPORT QSvgLine : public QSvgNode
{
public:
QSvgLine(QSvgNode *parent, const QLineF &line);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QLineF m_line;
};
class Q_SVG_PRIVATE_EXPORT QSvgPath : public QSvgNode
{
public:
QSvgPath(QSvgNode *parent, const QPainterPath &qpath);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
QPainterPath *qpath() {
return &m_path;
}
private:
QPainterPath m_path;
};
class Q_SVG_PRIVATE_EXPORT QSvgPolygon : public QSvgNode
{
public:
QSvgPolygon(QSvgNode *parent, const QPolygonF &poly);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QPolygonF m_poly;
};
class Q_SVG_PRIVATE_EXPORT QSvgPolyline : public QSvgNode
{
public:
QSvgPolyline(QSvgNode *parent, const QPolygonF &poly);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
QPolygonF m_poly;
};
class Q_SVG_PRIVATE_EXPORT QSvgRect : public QSvgNode
{
public:
QSvgRect(QSvgNode *paren, const QRectF &rect, int rx=0, int ry=0);
Type type() const override;
void draw(QPainter *p, QSvgExtraStates &states) override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
void SetRect(QRectF rect);
QRectF &rect();
private:
QRectF m_rect;
int m_rx, m_ry;
};
class QSvgTspan;
class Q_SVG_PRIVATE_EXPORT QSvgText : public QSvgNode
{
public:
enum WhitespaceMode
{
Default,
Preserve
};
QSvgText(QSvgNode *parent, const QPointF &coord);
~QSvgText();
void setTextArea(const QSizeF &size);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
void addTspan(QSvgTspan *tspan) {m_tspans.append(tspan);}
void addText(const QString &text);
void addLineBreak() {m_tspans.append(LINEBREAK);}
void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;}
//QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
private:
static QSvgTspan * const LINEBREAK;
QPointF m_coord;
// 'm_tspans' is also used to store characters outside tspans and line breaks.
// If a 'm_tspan' item is null, it indicates a line break.
QVector<QSvgTspan *> m_tspans;
Type m_type;
QSizeF m_size;
WhitespaceMode m_mode;
public:
void draw(QPainter *p, QSvgExtraStates &states,QRectF bounds,QTransform &oldTransform,QRectF &sourceRect,QMatrix &b);
QVector<QSvgTspan *>&Tspans()
{
return m_tspans;
}
};
class Q_SVG_PRIVATE_EXPORT QSvgTspan : public QSvgNode
{
public:
// tspans are also used to store normal text, so the 'isProperTspan' is used to separate text from tspan.
QSvgTspan(QSvgNode *parent, bool isProperTspan = true)
: QSvgNode(parent), m_mode(QSvgText::Default), m_isTspan(isProperTspan)
{
}
~QSvgTspan() { };
Type type() const override { return TSPAN; }
void draw(QPainter *, QSvgExtraStates &) override { Q_ASSERT(!"Tspans should be drawn through QSvgText::draw()."); }
void addText(const QString &text) {m_text += text;}
const QString &text() const {return m_text;}
bool isTspan() const {return m_isTspan;}
void setWhitespaceMode(QSvgText::WhitespaceMode mode) {m_mode = mode;}
QSvgText::WhitespaceMode whitespaceMode() const {return m_mode;}
private:
QString m_text;
QSvgText::WhitespaceMode m_mode;
bool m_isTspan;
};
class QSvgUse : public QSvgNode
{
public:
QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link);
QSvgUse(const QPointF &start, QSvgNode *parent, const QString &linkId)
: QSvgUse(start, parent, nullptr)
{ m_linkId = linkId; }
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
bool isResolved() const { return m_link != nullptr; }
QString linkId() const { return m_linkId; }
void setLink(QSvgNode *link) { m_link = link; }
private:
QSvgNode *m_link;
QPointF m_start;
QString m_linkId;
mutable bool m_recursing;
};
class QSvgVideo : public QSvgNode
{
public:
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
};
QT_END_NAMESPACE
#endif // QSVGGRAPHICS_P_H

4120
svg/qsvghandler.cpp Normal file

File diff suppressed because it is too large Load Diff

196
svg/qsvghandler_p.h Normal file
View File

@ -0,0 +1,196 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGHANDLER_P_H
#define QSVGHANDLER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtCore/qxmlstream.h"
#include "QtCore/qhash.h"
#include "QtCore/qstack.h"
#include <QtCore/QLoggingCategory>
#include "qsvgstyle_p.h"
#include "private/qcssparser_p.h"
#include "qsvggraphics_p.h"
#include "qtsvgglobal_p.h"
QT_BEGIN_NAMESPACE
class QSvgNode;
class QSvgTinyDocument;
class QSvgHandler;
class QColor;
class QSvgStyleSelector;
class QXmlStreamReader;
#ifndef QT_NO_CSSPARSER
struct QSvgCssAttribute
{
QXmlStreamStringRef name;
QXmlStreamStringRef value;
};
#endif
class Q_SVG_PRIVATE_EXPORT QSvgHandler
{
public:
enum LengthType {
LT_PERCENT,
LT_PX,
LT_PC,
LT_PT,
LT_MM,
LT_CM,
LT_IN,
LT_OTHER
};
public:
QSvgHandler(QIODevice *device);
QSvgHandler(const QByteArray &data);
QSvgHandler(QXmlStreamReader *const data);
~QSvgHandler();
QIODevice *device() const;
QSvgTinyDocument *document() const;
inline bool ok() const {
return document() != 0 && !xml->hasError();
}
inline QString errorString() const { return xml->errorString(); }
inline int lineNumber() const { return xml->lineNumber(); }
void setDefaultCoordinateSystem(LengthType type);
LengthType defaultCoordinateSystem() const;
void pushColor(const QColor &color);
void pushColorCopy();
void popColor();
QColor currentColor() const;
#ifndef QT_NO_CSSPARSER
void setInStyle(bool b);
bool inStyle() const;
QSvgStyleSelector *selector() const;
#endif
void setAnimPeriod(int start, int end);
int animationDuration() const;
#ifndef QT_NO_CSSPARSER
void parseCSStoXMLAttrs(QString css, QVector<QSvgCssAttribute> *attributes);
#endif
inline QPen defaultPen() const
{ return m_defaultPen; }
public:
bool startElement(const QString &localName, const QXmlStreamAttributes &attributes);
bool endElement(const QStringRef &localName);
bool characters(const QStringRef &str);
bool processingInstruction(const QString &target, const QString &data);
private:
void init();
QSvgTinyDocument *m_doc;
QStack<QSvgNode*> m_nodes;
QList<QSvgNode*> m_resolveNodes;
enum CurrentNode
{
Unknown,
Graphics,
Style
};
QStack<CurrentNode> m_skipNodes;
/*!
Follows the depths of elements. The top is current xml:space
value that applies for a given element.
*/
QStack<QSvgText::WhitespaceMode> m_whitespaceMode;
QSvgRefCounter<QSvgStyleProperty> m_style;
LengthType m_defaultCoords;
QStack<QColor> m_colorStack;
QStack<int> m_colorTagCount;
int m_animEnd;
QXmlStreamReader *const xml;
#ifndef QT_NO_CSSPARSER
bool m_inStyle;
QSvgStyleSelector *m_selector;
QCss::Parser m_cssParser;
#endif
void parse();
void resolveGradients(QSvgNode *node);
void resolveNodes();
QPen m_defaultPen;
/**
* Whether we own the variable xml, and hence whether
* we need to delete it.
*/
const bool m_ownsReader;
};
Q_DECLARE_LOGGING_CATEGORY(lcSvgHandler)
QT_END_NAMESPACE
#endif // QSVGHANDLER_P_H

350
svg/qsvgnode.cpp Normal file
View File

@ -0,0 +1,350 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgnode_p.h"
#include "qsvgtinydocument_p.h"
#include "qdebug.h"
#include "qstack.h"
QT_BEGIN_NAMESPACE
QSvgNode::QSvgNode(QSvgNode *parent)
: m_parent(parent),
m_visible(true),
m_displayMode(BlockMode)
{
}
QSvgNode::~QSvgNode()
{
}
bool QSvgNode::isDescendantOf(const QSvgNode *parent) const
{
const QSvgNode *n = this;
while (n) {
if (n == parent)
return true;
n = n->m_parent;
}
return false;
}
void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id)
{
//qDebug()<<"appending "<<prop->type()<< " ("<< id <<") "<<"to "<<this<<this->type();
QSvgTinyDocument *doc;
switch (prop->type()) {
case QSvgStyleProperty::QUALITY:
m_style.quality = static_cast<QSvgQualityStyle*>(prop);
break;
case QSvgStyleProperty::FILL:
m_style.fill = static_cast<QSvgFillStyle*>(prop);
break;
case QSvgStyleProperty::VIEWPORT_FILL:
m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop);
break;
case QSvgStyleProperty::FONT:
m_style.font = static_cast<QSvgFontStyle*>(prop);
break;
case QSvgStyleProperty::STROKE:
m_style.stroke = static_cast<QSvgStrokeStyle*>(prop);
break;
case QSvgStyleProperty::SOLID_COLOR:
m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop);
doc = document();
if (doc && !id.isEmpty())
doc->addNamedStyle(id, m_style.solidColor);
break;
case QSvgStyleProperty::GRADIENT:
m_style.gradient = static_cast<QSvgGradientStyle*>(prop);
doc = document();
if (doc && !id.isEmpty())
doc->addNamedStyle(id, m_style.gradient);
break;
case QSvgStyleProperty::TRANSFORM:
m_style.transform = static_cast<QSvgTransformStyle*>(prop);
break;
case QSvgStyleProperty::ANIMATE_COLOR:
m_style.animateColor = static_cast<QSvgAnimateColor*>(prop);
break;
case QSvgStyleProperty::ANIMATE_TRANSFORM:
m_style.animateTransforms.append(
static_cast<QSvgAnimateTransform*>(prop));
break;
case QSvgStyleProperty::OPACITY:
m_style.opacity = static_cast<QSvgOpacityStyle*>(prop);
break;
case QSvgStyleProperty::COMP_OP:
m_style.compop = static_cast<QSvgCompOpStyle*>(prop);
break;
default:
qDebug("QSvgNode: Trying to append unknown property!");
break;
}
}
void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const
{
m_style.apply(p, this, states);
}
void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const
{
m_style.revert(p, states);
}
QSvgStyleProperty * QSvgNode::styleProperty(QSvgStyleProperty::Type type) const
{
const QSvgNode *node = this;
while (node) {
switch (type) {
case QSvgStyleProperty::QUALITY:
if (node->m_style.quality)
return node->m_style.quality;
break;
case QSvgStyleProperty::FILL:
if (node->m_style.fill)
return node->m_style.fill;
break;
case QSvgStyleProperty::VIEWPORT_FILL:
if (m_style.viewportFill)
return node->m_style.viewportFill;
break;
case QSvgStyleProperty::FONT:
if (node->m_style.font)
return node->m_style.font;
break;
case QSvgStyleProperty::STROKE:
if (node->m_style.stroke)
return node->m_style.stroke;
break;
case QSvgStyleProperty::SOLID_COLOR:
if (node->m_style.solidColor)
return node->m_style.solidColor;
break;
case QSvgStyleProperty::GRADIENT:
if (node->m_style.gradient)
return node->m_style.gradient;
break;
case QSvgStyleProperty::TRANSFORM:
if (node->m_style.transform)
return node->m_style.transform;
break;
case QSvgStyleProperty::ANIMATE_COLOR:
if (node->m_style.animateColor)
return node->m_style.animateColor;
break;
case QSvgStyleProperty::ANIMATE_TRANSFORM:
if (!node->m_style.animateTransforms.isEmpty())
return node->m_style.animateTransforms.first();
break;
case QSvgStyleProperty::OPACITY:
if (node->m_style.opacity)
return node->m_style.opacity;
break;
case QSvgStyleProperty::COMP_OP:
if (node->m_style.compop)
return node->m_style.compop;
break;
default:
break;
}
node = node->parent();
}
return 0;
}
QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const
{
QString rid = id;
if (rid.startsWith(QLatin1Char('#')))
rid.remove(0, 1);
QSvgTinyDocument *doc = document();
return doc ? doc->namedStyle(rid) : 0;
}
QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const
{
return QRectF(0, 0, 0, 0);
}
QRectF QSvgNode::transformedBounds() const
{
if (!m_cachedBounds.isEmpty())
return m_cachedBounds;
QImage dummy(1, 1, QImage::Format_RGB32);
QPainter p(&dummy);
QSvgExtraStates states;
QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin);
pen.setMiterLimit(4);
p.setPen(pen);
QStack<QSvgNode*> parentApplyStack;
QSvgNode *parent = m_parent;
while (parent) {
parentApplyStack.push(parent);
parent = parent->parent();
}
for (int i = parentApplyStack.size() - 1; i >= 0; --i)
parentApplyStack[i]->applyStyle(&p, states);
p.setWorldTransform(QTransform());
m_cachedBounds = transformedBounds(&p, states);
return m_cachedBounds;
}
QSvgTinyDocument * QSvgNode::document() const
{
QSvgTinyDocument *doc = 0;
QSvgNode *node = const_cast<QSvgNode*>(this);
while (node && node->type() != QSvgNode::DOC) {
node = node->parent();
}
doc = static_cast<QSvgTinyDocument*>(node);
return doc;
}
void QSvgNode::setRequiredFeatures(const QStringList &lst)
{
m_requiredFeatures = lst;
}
const QStringList & QSvgNode::requiredFeatures() const
{
return m_requiredFeatures;
}
void QSvgNode::setRequiredExtensions(const QStringList &lst)
{
m_requiredExtensions = lst;
}
const QStringList & QSvgNode::requiredExtensions() const
{
return m_requiredExtensions;
}
void QSvgNode::setRequiredLanguages(const QStringList &lst)
{
m_requiredLanguages = lst;
}
const QStringList & QSvgNode::requiredLanguages() const
{
return m_requiredLanguages;
}
void QSvgNode::setRequiredFormats(const QStringList &lst)
{
m_requiredFormats = lst;
}
const QStringList & QSvgNode::requiredFormats() const
{
return m_requiredFormats;
}
void QSvgNode::setRequiredFonts(const QStringList &lst)
{
m_requiredFonts = lst;
}
const QStringList & QSvgNode::requiredFonts() const
{
return m_requiredFonts;
}
void QSvgNode::setVisible(bool visible)
{
//propagate visibility change of true to the parent
//not propagating false is just a small performance
//degradation since we'll iterate over children without
//drawing any of them
if (m_parent && visible && !m_parent->isVisible())
m_parent->setVisible(true);
m_visible = visible;
}
QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const
{
applyStyle(p, states);
QRectF rect = bounds(p, states);
revertStyle(p, states);
return rect;
}
void QSvgNode::setNodeId(const QString &i)
{
m_id = i;
}
void QSvgNode::setXmlClass(const QString &str)
{
m_class = str;
}
void QSvgNode::setDisplayMode(DisplayMode mode)
{
m_displayMode = mode;
}
QSvgNode::DisplayMode QSvgNode::displayMode() const
{
return m_displayMode;
}
qreal QSvgNode::strokeWidth(QPainter *p)
{
QPen pen = p->pen();
if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic())
return 0;
return pen.widthF();
}
QT_END_NAMESPACE

203
svg/qsvgnode_p.h Normal file
View File

@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGNODE_P_H
#define QSVGNODE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsvgstyle_p.h"
#include "qtsvgglobal_p.h"
#include "QtCore/qstring.h"
#include "QtCore/qhash.h"
QT_BEGIN_NAMESPACE
class QPainter;
class QSvgTinyDocument;
class Q_SVG_PRIVATE_EXPORT QSvgNode
{
public:
enum Type
{
DOC,
G,
DEFS,
SWITCH,
ANIMATION,
ARC,
CIRCLE,
ELLIPSE,
IMAGE,
LINE,
PATH,
POLYGON,
POLYLINE,
RECT,
TEXT,
TEXTAREA,
TSPAN,
USE,
VIDEO
};
enum DisplayMode {
InlineMode,
BlockMode,
ListItemMode,
RunInMode,
CompactMode,
MarkerMode,
TableMode,
InlineTableMode,
TableRowGroupMode,
TableHeaderGroupMode,
TableFooterGroupMode,
TableRowMode,
TableColumnGroupMode,
TableColumnMode,
TableCellMode,
TableCaptionMode,
NoneMode,
InheritMode
};
public:
QSvgNode(QSvgNode *parent=0);
virtual ~QSvgNode();
virtual void draw(QPainter *p, QSvgExtraStates &states) =0;
QSvgNode *parent() const;
bool isDescendantOf(const QSvgNode *parent) const;
void appendStyleProperty(QSvgStyleProperty *prop, const QString &id);
void applyStyle(QPainter *p, QSvgExtraStates &states) const;
void revertStyle(QPainter *p, QSvgExtraStates &states) const;
QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const;
QSvgFillStyleProperty *styleProperty(const QString &id) const;
QSvgTinyDocument *document() const;
virtual Type type() const =0;
virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const;
virtual QRectF transformedBounds(QPainter *p, QSvgExtraStates &states) const;
QRectF transformedBounds() const;
void setRequiredFeatures(const QStringList &lst);
const QStringList & requiredFeatures() const;
void setRequiredExtensions(const QStringList &lst);
const QStringList & requiredExtensions() const;
void setRequiredLanguages(const QStringList &lst);
const QStringList & requiredLanguages() const;
void setRequiredFormats(const QStringList &lst);
const QStringList & requiredFormats() const;
void setRequiredFonts(const QStringList &lst);
const QStringList & requiredFonts() const;
void setVisible(bool visible);
bool isVisible() const;
void setDisplayMode(DisplayMode display);
DisplayMode displayMode() const;
QString nodeId() const;
void setNodeId(const QString &i);
QString xmlClass() const;
void setXmlClass(const QString &str);
protected:
mutable QSvgStyle m_style;
static qreal strokeWidth(QPainter *p);
private:
QSvgNode *m_parent;
QStringList m_requiredFeatures;
QStringList m_requiredExtensions;
QStringList m_requiredLanguages;
QStringList m_requiredFormats;
QStringList m_requiredFonts;
bool m_visible;
QString m_id;
QString m_class;
DisplayMode m_displayMode;
mutable QRectF m_cachedBounds;
friend class QSvgTinyDocument;
};
inline QSvgNode *QSvgNode::parent() const
{
return m_parent;
}
inline bool QSvgNode::isVisible() const
{
return m_visible;
}
inline QString QSvgNode::nodeId() const
{
return m_id;
}
inline QString QSvgNode::xmlClass() const
{
return m_class;
}
QT_END_NAMESPACE
#endif // QSVGNODE_P_H

500
svg/qsvgrenderer.cpp Normal file
View File

@ -0,0 +1,500 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgrenderer.h"
#ifndef QT_NO_SVGRENDERER
#include "qsvgtinydocument_p.h"
#include "qbytearray.h"
#include "qtimer.h"
#include "qdebug.h"
#include "private/qobject_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QSvgRenderer
\inmodule QtSvg
\ingroup painting
\brief The QSvgRenderer class is used to draw the contents of SVG files onto paint devices.
\since 4.1
\reentrant
Using QSvgRenderer, Scalable Vector Graphics (SVG) can be rendered onto any QPaintDevice
subclass, including QWidget, QImage, and QGLWidget.
QSvgRenderer provides an API that supports basic features of SVG rendering, such as loading
and rendering of static drawings, and more interactive features like animation. Since the
rendering is performed using QPainter, SVG drawings can be rendered on any subclass of
QPaintDevice.
SVG drawings are either loaded when an QSvgRenderer is constructed, or loaded later
using the load() functions. Data is either supplied directly as serialized XML, or
indirectly using a file name. If a valid file has been loaded, either when the renderer
is constructed or at some later time, isValid() returns true; otherwise it returns false.
QSvgRenderer provides the render() slot to render the current document, or the current
frame of an animated document, using a given painter.
The defaultSize() function provides information about the amount of space that is required
to render the currently loaded SVG file. This is useful for paint devices, such as QWidget,
that often need to supply a size hint to their parent layout.
The default size of a drawing may differ from its visible area, found using the \l viewBox
property.
Animated SVG drawings are supported, and can be controlled with a simple collection of
functions and properties:
\list
\li The animated() function indicates whether a drawing contains animation information.
\omit
\li The animationDuration() function provides the duration in milliseconds of the
animation, without taking any looping into account.
\li The \l currentFrame property contains the current frame of the animation.
\endomit
\li The \l framesPerSecond property contains the rate at which the animation plays.
\endlist
Finally, the QSvgRenderer class provides the repaintNeeded() signal which is emitted
whenever the rendering of the document needs to be updated.
\sa QSvgWidget, {Qt SVG C++ Classes}, {SVG Viewer Example}, QPicture
*/
class QSvgRendererPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSvgRenderer)
public:
explicit QSvgRendererPrivate()
: QObjectPrivate(),
render(0), timer(0),
fps(30)
{}
~QSvgRendererPrivate()
{
delete render;
}
static void callRepaintNeeded(QSvgRenderer *const q);
QSvgTinyDocument *render;
QTimer *timer;
int fps;
};
/*!
Constructs a new renderer with the given \a parent.
*/
QSvgRenderer::QSvgRenderer(QObject *parent)
: QObject(*(new QSvgRendererPrivate), parent)
{
}
/*!
Constructs a new renderer with the given \a parent and loads the contents of the
SVG file with the specified \a filename.
*/
QSvgRenderer::QSvgRenderer(const QString &filename, QObject *parent)
: QObject(*new QSvgRendererPrivate, parent)
{
load(filename);
}
/*!
Constructs a new renderer with the given \a parent and loads the SVG data
from the byte array specified by \a contents.
*/
QSvgRenderer::QSvgRenderer(const QByteArray &contents, QObject *parent)
: QObject(*new QSvgRendererPrivate, parent)
{
load(contents);
}
/*!
\since 4.5
Constructs a new renderer with the given \a parent and loads the SVG data
using the stream reader specified by \a contents.
*/
QSvgRenderer::QSvgRenderer(QXmlStreamReader *contents, QObject *parent)
: QObject(*new QSvgRendererPrivate, parent)
{
load(contents);
}
/*!
Destroys the renderer.
*/
QSvgRenderer::~QSvgRenderer()
{
}
/*!
Returns true if there is a valid current document; otherwise returns false.
*/
bool QSvgRenderer::isValid() const
{
Q_D(const QSvgRenderer);
return d->render;
}
/*!
Returns the default size of the document contents.
*/
QSize QSvgRenderer::defaultSize() const
{
Q_D(const QSvgRenderer);
if (d->render)
return d->render->size();
else
return QSize();
}
/*!
Returns viewBoxF().toRect().
\sa viewBoxF()
*/
QRect QSvgRenderer::viewBox() const
{
Q_D(const QSvgRenderer);
if (d->render)
return d->render->viewBox().toRect();
else
return QRect();
}
/*!
\property QSvgRenderer::viewBox
\brief the rectangle specifying the visible area of the document in logical coordinates
\since 4.2
*/
void QSvgRenderer::setViewBox(const QRect &viewbox)
{
Q_D(QSvgRenderer);
if (d->render)
d->render->setViewBox(viewbox);
}
/*!
Returns true if the current document contains animated elements; otherwise
returns false.
\sa framesPerSecond()
*/
bool QSvgRenderer::animated() const
{
Q_D(const QSvgRenderer);
if (d->render)
return d->render->animated();
else
return false;
}
/*!
\property QSvgRenderer::framesPerSecond
\brief the number of frames per second to be shown
The number of frames per second is 0 if the current document is not animated.
\sa animated()
*/
int QSvgRenderer::framesPerSecond() const
{
Q_D(const QSvgRenderer);
return d->fps;
}
void QSvgRenderer::setFramesPerSecond(int num)
{
Q_D(QSvgRenderer);
if (num < 0) {
qWarning("QSvgRenderer::setFramesPerSecond: Cannot set negative value %d", num);
return;
}
d->fps = num;
}
/*!
\property QSvgRenderer::currentFrame
\brief the current frame of the document's animation, or 0 if the document is not animated
\internal
\sa animationDuration(), framesPerSecond, animated()
*/
/*!
\internal
*/
int QSvgRenderer::currentFrame() const
{
Q_D(const QSvgRenderer);
return d->render->currentFrame();
}
/*!
\internal
*/
void QSvgRenderer::setCurrentFrame(int frame)
{
Q_D(QSvgRenderer);
d->render->setCurrentFrame(frame);
}
/*!
\internal
Returns the number of frames in the animation, or 0 if the current document is not
animated.
\sa animated(), framesPerSecond
*/
int QSvgRenderer::animationDuration() const
{
Q_D(const QSvgRenderer);
return d->render->animationDuration();
}
/*!
\internal
\since 4.5
We can't have template functions, that's loadDocument(), as friends, for this
code, so we let this function be a friend of QSvgRenderer instead.
*/
void QSvgRendererPrivate::callRepaintNeeded(QSvgRenderer *const q)
{
emit q->repaintNeeded();
}
template<typename TInputType>
static bool loadDocument(QSvgRenderer *const q,
QSvgRendererPrivate *const d,
const TInputType &in)
{
delete d->render;
d->render = QSvgTinyDocument::load(in);
if (d->render && d->render->animated() && d->fps > 0) {
if (!d->timer)
d->timer = new QTimer(q);
else
d->timer->stop();
q->connect(d->timer, SIGNAL(timeout()),
q, SIGNAL(repaintNeeded()));
d->timer->start(1000/d->fps);
} else if (d->timer) {
d->timer->stop();
}
//force first update
QSvgRendererPrivate::callRepaintNeeded(q);
return d->render;
}
/*!
Loads the SVG file specified by \a filename, returning true if the content
was successfully parsed; otherwise returns false.
*/
bool QSvgRenderer::load(const QString &filename)
{
Q_D(QSvgRenderer);
return loadDocument(this, d, filename);
}
/*!
Loads the specified SVG format \a contents, returning true if the content
was successfully parsed; otherwise returns false.
*/
bool QSvgRenderer::load(const QByteArray &contents)
{
Q_D(QSvgRenderer);
return loadDocument(this, d, contents);
}
/*!
Loads the specified SVG in \a contents, returning true if the content
was successfully parsed; otherwise returns false.
The reader will be used from where it currently is positioned. If \a contents
is \c null, behavior is undefined.
\since 4.5
*/
bool QSvgRenderer::load(QXmlStreamReader *contents)
{
Q_D(QSvgRenderer);
return loadDocument(this, d, contents);
}
/*!
Renders the current document, or the current frame of an animated
document, using the given \a painter.
*/
void QSvgRenderer::render(QPainter *painter)
{
Q_D(QSvgRenderer);
if (d->render) {
d->render->draw(painter);
}
}
/*!
\fn void QSvgRenderer::repaintNeeded()
This signal is emitted whenever the rendering of the document
needs to be updated, usually for the purposes of animation.
*/
/*!
Renders the given element with \a elementId using the given \a painter
on the specified \a bounds. If the bounding rectangle is not specified
the SVG element is mapped to the whole paint device.
*/
void QSvgRenderer::render(QPainter *painter, const QString &elementId,
const QRectF &bounds)
{
Q_D(QSvgRenderer);
if (d->render) {
d->render->draw(painter, elementId, bounds);
}
}
/*!
Renders the current document, or the current frame of an animated
document, using the given \a painter on the specified \a bounds within
the painter. If the bounding rectangle is not specified
the SVG file is mapped to the whole paint device.
*/
void QSvgRenderer::render(QPainter *painter, const QRectF &bounds)
{
Q_D(QSvgRenderer);
if (d->render) {
d->render->draw(painter, bounds);
}
}
QRectF QSvgRenderer::viewBoxF() const
{
Q_D(const QSvgRenderer);
if (d->render)
return d->render->viewBox();
else
return QRect();
}
void QSvgRenderer::setViewBox(const QRectF &viewbox)
{
Q_D(QSvgRenderer);
if (d->render)
d->render->setViewBox(viewbox);
}
/*!
\since 4.2
Returns bounding rectangle of the item with the given \a id.
The transformation matrix of parent elements is not affecting
the bounds of the element.
\sa matrixForElement()
*/
QRectF QSvgRenderer::boundsOnElement(const QString &id) const
{
Q_D(const QSvgRenderer);
QRectF bounds;
if (d->render)
bounds = d->render->boundsOnElement(id);
return bounds;
}
/*!
\since 4.2
Returns true if the element with the given \a id exists
in the currently parsed SVG file and is a renderable
element.
Note: this method returns true only for elements that
can be rendered. Which implies that elements that are considered
part of the fill/stroke style properties, e.g. radialGradients
even tough marked with "id" attributes will not be found by this
method.
*/
bool QSvgRenderer::elementExists(const QString &id) const
{
Q_D(const QSvgRenderer);
bool exists = false;
if (d->render)
exists = d->render->elementExists(id);
return exists;
}
/*!
\since 4.2
Returns the transformation matrix for the element
with the given \a id. The matrix is a product of
the transformation of the element's parents. The transformation of
the element itself is not included.
To find the bounding rectangle of the element in logical coordinates,
you can apply the matrix on the rectangle returned from boundsOnElement().
\sa boundsOnElement()
*/
QMatrix QSvgRenderer::matrixForElement(const QString &id) const
{
Q_D(const QSvgRenderer);
QMatrix mat;
if (d->render)
mat = d->render->matrixForElement(id);
return mat;
}
QT_END_NAMESPACE
#include "moc_qsvgrenderer.cpp"
#endif // QT_NO_SVGRENDERER

114
svg/qsvgrenderer.h Normal file
View File

@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGRENDERER_H
#define QSVGRENDERER_H
#include <QtGui/qmatrix.h>
#ifndef QT_NO_SVGRENDERER
#include <QtCore/qobject.h>
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
#include <QtCore/qxmlstream.h>
#include <QtSvg/qtsvgglobal.h>
QT_BEGIN_NAMESPACE
class QSvgRendererPrivate;
class QPainter;
class QByteArray;
class Q_SVG_EXPORT QSvgRenderer : public QObject
{
Q_OBJECT
Q_PROPERTY(QRectF viewBox READ viewBoxF WRITE setViewBox)
Q_PROPERTY(int framesPerSecond READ framesPerSecond WRITE setFramesPerSecond)
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame)
public:
QSvgRenderer(QObject *parent = nullptr);
QSvgRenderer(const QString &filename, QObject *parent = nullptr);
QSvgRenderer(const QByteArray &contents, QObject *parent = nullptr);
QSvgRenderer(QXmlStreamReader *contents, QObject *parent = nullptr);
~QSvgRenderer();
bool isValid() const;
QSize defaultSize() const;
QRect viewBox() const;
QRectF viewBoxF() const;
void setViewBox(const QRect &viewbox);
void setViewBox(const QRectF &viewbox);
bool animated() const;
int framesPerSecond() const;
void setFramesPerSecond(int num);
int currentFrame() const;
void setCurrentFrame(int);
int animationDuration() const;//in seconds
QRectF boundsOnElement(const QString &id) const;
bool elementExists(const QString &id) const;
QMatrix matrixForElement(const QString &id) const;
public Q_SLOTS:
bool load(const QString &filename);
bool load(const QByteArray &contents);
bool load(QXmlStreamReader *contents);
void render(QPainter *p);
void render(QPainter *p, const QRectF &bounds);
void render(QPainter *p, const QString &elementId,
const QRectF &bounds=QRectF());
Q_SIGNALS:
void repaintNeeded();
private:
Q_DECLARE_PRIVATE(QSvgRenderer)
};
QT_END_NAMESPACE
#endif // QT_NO_SVGRENDERER
#endif // QSVGRENDERER_H

377
svg/qsvgstructure.cpp Normal file
View File

@ -0,0 +1,377 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgstructure_p.h"
#include "qsvgnode_p.h"
#include "qsvgstyle_p.h"
#include "qsvgtinydocument_p.h"
#include "qpainter.h"
#include "qlocale.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
QSvgG::QSvgG(QSvgNode *parent)
: QSvgStructureNode(parent)
{
}
QSvgStructureNode::~QSvgStructureNode()
{
qDeleteAll(m_renderers);
}
void QSvgG::draw(QPainter *p, QSvgExtraStates &states)
{
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
while (itr != m_renderers.end()) {
QSvgNode *node = *itr;
if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
node->draw(p, states);
++itr;
}
revertStyle(p, states);
}
QSvgNode::Type QSvgG::type() const
{
return G;
}
QSvgStructureNode::QSvgStructureNode(QSvgNode *parent)
:QSvgNode(parent)
{
}
QSvgNode * QSvgStructureNode::scopeNode(const QString &id) const
{
QSvgTinyDocument *doc = document();
return doc ? doc->namedNode(id) : 0;
}
void QSvgStructureNode::addChild(QSvgNode *child, const QString &id)
{
m_renderers.append(child);
if (id.isEmpty())
return; //we can't add it to scope without id
QSvgTinyDocument *doc = document();
if (doc)
doc->addNamedNode(id, child);
}
QSvgDefs::QSvgDefs(QSvgNode *parent)
: QSvgStructureNode(parent)
{
}
void QSvgDefs::draw(QPainter *, QSvgExtraStates &)
{
//noop
}
QSvgNode::Type QSvgDefs::type() const
{
return DEFS;
}
/*
Below is a lookup function based on the gperf output using the following set:
http://www.w3.org/Graphics/SVG/feature/1.2/#SVG
http://www.w3.org/Graphics/SVG/feature/1.2/#SVG-static
http://www.w3.org/Graphics/SVG/feature/1.2/#CoreAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#Structure
http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessing
http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessingAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#Image
http://www.w3.org/Graphics/SVG/feature/1.2/#Prefetch
http://www.w3.org/Graphics/SVG/feature/1.2/#Shape
http://www.w3.org/Graphics/SVG/feature/1.2/#Text
http://www.w3.org/Graphics/SVG/feature/1.2/#PaintAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#OpacityAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#GraphicsAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#Gradient
http://www.w3.org/Graphics/SVG/feature/1.2/#SolidColor
http://www.w3.org/Graphics/SVG/feature/1.2/#XlinkAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#ExternalResourcesRequiredAttribute
http://www.w3.org/Graphics/SVG/feature/1.2/#Font
http://www.w3.org/Graphics/SVG/feature/1.2/#Hyperlinking
http://www.w3.org/Graphics/SVG/feature/1.2/#Extensibility
*/
// ----- begin of generated code -----
/* C code produced by gperf version 3.0.2 */
/* Command-line: gperf -c -L c svg */
/* Computed positions: -k'45-46' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
#endif
enum {
TOTAL_KEYWORDS = 20,
MIN_WORD_LENGTH = 47,
MAX_WORD_LENGTH = 78,
MIN_HASH_VALUE = 48,
MAX_HASH_VALUE = 88
};
/* maximum key range = 41, duplicates = 0 */
inline static bool isSupportedSvgFeature(const QString &str)
{
static const unsigned char asso_values[] = {
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 0, 89, 5,
15, 5, 0, 10, 89, 89, 89, 89, 89, 0,
15, 89, 89, 0, 0, 89, 5, 89, 0, 89,
89, 89, 89, 89, 89, 89, 89, 0, 89, 89,
89, 0, 89, 89, 0, 89, 89, 89, 0, 5,
89, 0, 0, 89, 5, 89, 0, 89, 89, 89,
5, 0, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 89, 89, 89, 89, 89
};
static const char * wordlist[] = {
"", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "",
"", "", "",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Text",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Shape",
"", "",
"http://www.w3.org/Graphics/SVG/feature/1.2/#SVG",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Structure",
"http://www.w3.org/Graphics/SVG/feature/1.2/#SolidColor",
"",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Hyperlinking",
"http://www.w3.org/Graphics/SVG/feature/1.2/#CoreAttribute",
"http://www.w3.org/Graphics/SVG/feature/1.2/#XlinkAttribute",
"http://www.w3.org/Graphics/SVG/feature/1.2/#SVG-static",
"http://www.w3.org/Graphics/SVG/feature/1.2/#OpacityAttribute",
"",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Gradient",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Font",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Image",
"http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessing",
"",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Extensibility",
"", "", "",
"http://www.w3.org/Graphics/SVG/feature/1.2/#GraphicsAttribute",
"http://www.w3.org/Graphics/SVG/feature/1.2/#Prefetch",
"http://www.w3.org/Graphics/SVG/feature/1.2/#PaintAttribute",
"http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessingAttribute",
"", "", "", "", "", "", "", "", "",
"", "", "", "",
"http://www.w3.org/Graphics/SVG/feature/1.2/#ExternalResourcesRequiredAttribute"
};
if (str.length() <= MAX_WORD_LENGTH && str.length() >= MIN_WORD_LENGTH) {
const int key = str.length()
+ asso_values[str.at(45).unicode()]
+ asso_values[str.at(44).unicode()];
if (key <= MAX_HASH_VALUE && key >= 0)
return str == QLatin1String(wordlist[key]);
}
return false;
}
// ----- end of generated code -----
static inline bool isSupportedSvgExtension(const QString &)
{
return false;
}
QSvgSwitch::QSvgSwitch(QSvgNode *parent)
: QSvgStructureNode(parent)
{
init();
}
void QSvgSwitch::draw(QPainter *p, QSvgExtraStates &states)
{
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
while (itr != m_renderers.end()) {
QSvgNode *node = *itr;
if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) {
const QStringList &features = node->requiredFeatures();
const QStringList &extensions = node->requiredExtensions();
const QStringList &languages = node->requiredLanguages();
const QStringList &formats = node->requiredFormats();
const QStringList &fonts = node->requiredFonts();
bool okToRender = true;
if (!features.isEmpty()) {
QStringList::const_iterator sitr = features.constBegin();
for (; sitr != features.constEnd(); ++sitr) {
if (!isSupportedSvgFeature(*sitr)) {
okToRender = false;
break;
}
}
}
if (okToRender && !extensions.isEmpty()) {
QStringList::const_iterator sitr = extensions.constBegin();
for (; sitr != extensions.constEnd(); ++sitr) {
if (!isSupportedSvgExtension(*sitr)) {
okToRender = false;
break;
}
}
}
if (okToRender && !languages.isEmpty()) {
QStringList::const_iterator sitr = languages.constBegin();
okToRender = false;
for (; sitr != languages.constEnd(); ++sitr) {
if ((*sitr).startsWith(m_systemLanguagePrefix)) {
okToRender = true;
break;
}
}
}
if (okToRender && !formats.isEmpty()) {
okToRender = false;
}
if (okToRender && !fonts.isEmpty()) {
okToRender = false;
}
if (okToRender) {
node->draw(p, states);
break;
}
}
++itr;
}
revertStyle(p, states);
}
QSvgNode::Type QSvgSwitch::type() const
{
return SWITCH;
}
void QSvgSwitch::init()
{
QLocale locale;
m_systemLanguage = locale.name().replace(QLatin1Char('_'), QLatin1Char('-'));
int idx = m_systemLanguage.indexOf(QLatin1Char('-'));
m_systemLanguagePrefix = m_systemLanguage.mid(0, idx);
}
QRectF QSvgStructureNode::bounds(QPainter *p, QSvgExtraStates &states) const
{
QRectF bounds;
for (QSvgNode *node : qAsConst(m_renderers))
bounds |= node->transformedBounds(p, states);
return bounds;
}
QSvgNode * QSvgStructureNode::previousSiblingNode(QSvgNode *n) const
{
QSvgNode *prev = 0;
QList<QSvgNode*>::const_iterator itr = m_renderers.constBegin();
for (; itr != m_renderers.constEnd(); ++itr) {
QSvgNode *node = *itr;
if (node == n)
return prev;
prev = node;
}
return prev;
}
QT_END_NAMESPACE

114
svg/qsvgstructure_p.h Normal file
View File

@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGSTRUCTURE_P_H
#define QSVGSTRUCTURE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsvgnode_p.h"
#include "qtsvgglobal_p.h"
#include "QtCore/qlist.h"
#include "QtCore/qhash.h"
QT_BEGIN_NAMESPACE
class QSvgTinyDocument;
class QSvgNode;
class QPainter;
class QSvgDefs;
class Q_SVG_PRIVATE_EXPORT QSvgStructureNode : public QSvgNode
{
public:
QSvgStructureNode(QSvgNode *parent);
~QSvgStructureNode();
QSvgNode *scopeNode(const QString &id) const;
void addChild(QSvgNode *child, const QString &id);
QRectF bounds(QPainter *p, QSvgExtraStates &states) const override;
QSvgNode *previousSiblingNode(QSvgNode *n) const;
QList<QSvgNode*> renderers() const { return m_renderers; }
protected:
QList<QSvgNode*> m_renderers;
QHash<QString, QSvgNode*> m_scope;
QList<QSvgStructureNode*> m_linkedScopes;
};
class Q_SVG_PRIVATE_EXPORT QSvgG : public QSvgStructureNode
{
public:
QSvgG(QSvgNode *parent);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
};
class Q_SVG_PRIVATE_EXPORT QSvgDefs : public QSvgStructureNode
{
public:
QSvgDefs(QSvgNode *parent);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
};
class Q_SVG_PRIVATE_EXPORT QSvgSwitch : public QSvgStructureNode
{
public:
QSvgSwitch(QSvgNode *parent);
void draw(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
private:
void init();
private:
QString m_systemLanguage;
QString m_systemLanguagePrefix;
};
QT_END_NAMESPACE
#endif // QSVGSTRUCTURE_P_H

969
svg/qsvgstyle.cpp Normal file
View File

@ -0,0 +1,969 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgstyle_p.h"
#include "qsvgfont_p.h"
#include "qsvggraphics_p.h"
#include "qsvgnode_p.h"
#include "qsvgtinydocument_p.h"
#include "qpainter.h"
#include "qpair.h"
#include "qcolor.h"
#include "qdebug.h"
#include "qmath.h"
#include "qnumeric.h"
QT_BEGIN_NAMESPACE
QSvgExtraStates::QSvgExtraStates()
: fillOpacity(1.0)
, strokeOpacity(1.0)
, svgFont(0)
, textAnchor(Qt::AlignLeft)
, fontWeight(400)
, fillRule(Qt::WindingFill)
, strokeDashOffset(0)
, vectorEffect(false)
{
}
QSvgStyleProperty::~QSvgStyleProperty()
{
}
void QSvgFillStyleProperty::apply(QPainter *, const QSvgNode *, QSvgExtraStates &)
{
Q_ASSERT(!"This should not be called!");
}
void QSvgFillStyleProperty::revert(QPainter *, QSvgExtraStates &)
{
Q_ASSERT(!"This should not be called!");
}
QSvgQualityStyle::QSvgQualityStyle(int color)
{
Q_UNUSED(color);
}
void QSvgQualityStyle::apply(QPainter *, const QSvgNode *, QSvgExtraStates &)
{
}
void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &)
{
}
QSvgFillStyle::QSvgFillStyle()
: m_style(0)
, m_fillRule(Qt::WindingFill)
, m_oldFillRule(Qt::WindingFill)
, m_fillOpacity(1.0)
, m_oldFillOpacity(0)
, m_gradientResolved(1)
, m_fillRuleSet(0)
, m_fillOpacitySet(0)
, m_fillSet(0)
{
}
void QSvgFillStyle::setFillRule(Qt::FillRule f)
{
m_fillRuleSet = 1;
m_fillRule = f;
}
void QSvgFillStyle::setFillOpacity(qreal opacity)
{
m_fillOpacitySet = 1;
m_fillOpacity = opacity;
}
void QSvgFillStyle::setFillStyle(QSvgFillStyleProperty* style)
{
m_style = style;
m_fillSet = 1;
}
void QSvgFillStyle::setBrush(QBrush brush)
{
m_fill = brush;
m_style = 0;
m_fillSet = 1;
}
void QSvgFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states)
{
m_oldFill = p->brush();
m_oldFillRule = states.fillRule;
m_oldFillOpacity = states.fillOpacity;
if (m_fillRuleSet)
states.fillRule = m_fillRule;
if (m_fillSet) {
if (m_style)
p->setBrush(m_style->brush(p, states));
else
p->setBrush(m_fill);
}
if (m_fillOpacitySet)
states.fillOpacity = m_fillOpacity;
}
void QSvgFillStyle::revert(QPainter *p, QSvgExtraStates &states)
{
if (m_fillOpacitySet)
states.fillOpacity = m_oldFillOpacity;
if (m_fillSet)
p->setBrush(m_oldFill);
if (m_fillRuleSet)
states.fillRule = m_oldFillRule;
}
QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush)
: m_viewportFill(brush)
{
}
void QSvgViewportFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
{
m_oldFill = p->brush();
p->setBrush(m_viewportFill);
}
void QSvgViewportFillStyle::revert(QPainter *p, QSvgExtraStates &)
{
p->setBrush(m_oldFill);
}
QSvgFontStyle::QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc)
: m_svgFont(font)
, m_doc(doc)
, m_familySet(0)
, m_sizeSet(0)
, m_styleSet(0)
, m_variantSet(0)
, m_weightSet(0)
, m_textAnchorSet(0)
{
}
QSvgFontStyle::QSvgFontStyle()
: m_svgFont(0)
, m_doc(0)
, m_familySet(0)
, m_sizeSet(0)
, m_styleSet(0)
, m_variantSet(0)
, m_weightSet(0)
, m_textAnchorSet(0)
{
}
int QSvgFontStyle::SVGToQtWeight(int weight) {
switch (weight) {
case 100:
case 200:
return QFont::Light;
case 300:
case 400:
return QFont::Normal;
case 500:
case 600:
return QFont::DemiBold;
case 700:
case 800:
return QFont::Bold;
case 900:
return QFont::Black;
}
return QFont::Normal;
}
void QSvgFontStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states)
{
m_oldQFont = p->font();
m_oldSvgFont = states.svgFont;
m_oldTextAnchor = states.textAnchor;
m_oldWeight = states.fontWeight;
if (m_textAnchorSet)
states.textAnchor = m_textAnchor;
QFont font = m_oldQFont;
if (m_familySet) {
states.svgFont = m_svgFont;
font.setFamily(m_qfont.family());
}
if (m_sizeSet)
font.setPointSizeF(m_qfont.pointSizeF());
if (m_styleSet)
font.setStyle(m_qfont.style());
if (m_variantSet)
font.setCapitalization(m_qfont.capitalization());
if (m_weightSet) {
if (m_weight == BOLDER) {
states.fontWeight = qMin(states.fontWeight + 100, 900);
} else if (m_weight == LIGHTER) {
states.fontWeight = qMax(states.fontWeight - 100, 100);
} else {
states.fontWeight = m_weight;
}
font.setWeight(SVGToQtWeight(states.fontWeight));
}
p->setFont(font);
}
void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &states)
{
p->setFont(m_oldQFont);
states.svgFont = m_oldSvgFont;
states.textAnchor = m_oldTextAnchor;
states.fontWeight = m_oldWeight;
}
QSvgStrokeStyle::QSvgStrokeStyle()
: m_strokeOpacity(1.0)
, m_oldStrokeOpacity(0.0)
, m_strokeDashOffset(0)
, m_oldStrokeDashOffset(0)
, m_style(0)
, m_gradientResolved(1)
, m_vectorEffect(0)
, m_oldVectorEffect(0)
, m_strokeSet(0)
, m_strokeDashArraySet(0)
, m_strokeDashOffsetSet(0)
, m_strokeLineCapSet(0)
, m_strokeLineJoinSet(0)
, m_strokeMiterLimitSet(0)
, m_strokeOpacitySet(0)
, m_strokeWidthSet(0)
, m_vectorEffectSet(0)
{
}
void QSvgStrokeStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states)
{
m_oldStroke = p->pen();
m_oldStrokeOpacity = states.strokeOpacity;
m_oldStrokeDashOffset = states.strokeDashOffset;
m_oldVectorEffect = states.vectorEffect;
QPen pen = p->pen();
qreal oldWidth = pen.widthF();
qreal width = m_stroke.widthF();
if (oldWidth == 0)
oldWidth = 1;
if (width == 0)
width = 1;
qreal scale = oldWidth / width;
if (m_strokeOpacitySet)
states.strokeOpacity = m_strokeOpacity;
if (m_vectorEffectSet)
states.vectorEffect = m_vectorEffect;
if (m_strokeSet) {
if (m_style)
pen.setBrush(m_style->brush(p, states));
else
pen.setBrush(m_stroke.brush());
}
if (m_strokeWidthSet)
pen.setWidthF(m_stroke.widthF());
bool setDashOffsetNeeded = false;
if (m_strokeDashOffsetSet) {
states.strokeDashOffset = m_strokeDashOffset;
setDashOffsetNeeded = true;
}
if (m_strokeDashArraySet) {
if (m_stroke.style() == Qt::SolidLine) {
pen.setStyle(Qt::SolidLine);
} else if (m_strokeWidthSet || oldWidth == 1) {
// If both width and dash array was set, the dash array is already scaled correctly.
pen.setDashPattern(m_stroke.dashPattern());
setDashOffsetNeeded = true;
} else {
// If dash array was set, but not the width, the dash array has to be scaled with respect to the old width.
QVector<qreal> dashes = m_stroke.dashPattern();
for (int i = 0; i < dashes.size(); ++i)
dashes[i] /= oldWidth;
pen.setDashPattern(dashes);
setDashOffsetNeeded = true;
}
} else if (m_strokeWidthSet && pen.style() != Qt::SolidLine && scale != 1) {
// If the width was set, but not the dash array, the old dash array must be scaled with respect to the new width.
QVector<qreal> dashes = pen.dashPattern();
for (int i = 0; i < dashes.size(); ++i)
dashes[i] *= scale;
pen.setDashPattern(dashes);
setDashOffsetNeeded = true;
}
if (m_strokeLineCapSet)
pen.setCapStyle(m_stroke.capStyle());
if (m_strokeLineJoinSet)
pen.setJoinStyle(m_stroke.joinStyle());
if (m_strokeMiterLimitSet)
pen.setMiterLimit(m_stroke.miterLimit());
// You can have dash offset on solid strokes in SVG files, but not in Qt.
// QPen::setDashOffset() will set the pen style to Qt::CustomDashLine,
// so don't call the method if the pen is solid.
if (setDashOffsetNeeded && pen.style() != Qt::SolidLine) {
qreal currentWidth = pen.widthF();
if (currentWidth == 0)
currentWidth = 1;
pen.setDashOffset(states.strokeDashOffset / currentWidth);
}
pen.setCosmetic(states.vectorEffect);
p->setPen(pen);
}
void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &states)
{
p->setPen(m_oldStroke);
states.strokeOpacity = m_oldStrokeOpacity;
states.strokeDashOffset = m_oldStrokeDashOffset;
states.vectorEffect = m_oldVectorEffect;
}
void QSvgStrokeStyle::setDashArray(const QVector<qreal> &dashes)
{
if (m_strokeWidthSet) {
QVector<qreal> d = dashes;
qreal w = m_stroke.widthF();
if (w != 0 && w != 1) {
for (int i = 0; i < d.size(); ++i)
d[i] /= w;
}
m_stroke.setDashPattern(d);
} else {
m_stroke.setDashPattern(dashes);
}
m_strokeDashArraySet = 1;
}
QSvgSolidColorStyle::QSvgSolidColorStyle(const QColor &color)
: m_solidColor(color)
{
}
QSvgGradientStyle::QSvgGradientStyle(QGradient *grad)
: m_gradient(grad), m_gradientStopsSet(false)
{
}
QBrush QSvgGradientStyle::brush(QPainter *, QSvgExtraStates &)
{
if (!m_link.isEmpty()) {
resolveStops();
}
// If the gradient is marked as empty, insert transparent black
if (!m_gradientStopsSet) {
m_gradient->setStops(QGradientStops() << QGradientStop(0.0, QColor(0, 0, 0, 0)));
m_gradientStopsSet = true;
}
QBrush b(*m_gradient);
if (!m_matrix.isIdentity())
b.setMatrix(m_matrix);
return b;
}
void QSvgGradientStyle::setMatrix(const QMatrix &mat)
{
m_matrix = mat;
}
QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans)
: m_transform(trans)
{
}
void QSvgTransformStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
{
m_oldWorldTransform = p->worldTransform();
p->setWorldTransform(m_transform, true);
}
void QSvgTransformStyle::revert(QPainter *p, QSvgExtraStates &)
{
p->setWorldTransform(m_oldWorldTransform, false /* don't combine */);
}
QSvgStyleProperty::Type QSvgQualityStyle::type() const
{
return QUALITY;
}
QSvgStyleProperty::Type QSvgFillStyle::type() const
{
return FILL;
}
QSvgStyleProperty::Type QSvgViewportFillStyle::type() const
{
return VIEWPORT_FILL;
}
QSvgStyleProperty::Type QSvgFontStyle::type() const
{
return FONT;
}
QSvgStyleProperty::Type QSvgStrokeStyle::type() const
{
return STROKE;
}
QSvgStyleProperty::Type QSvgSolidColorStyle::type() const
{
return SOLID_COLOR;
}
QSvgStyleProperty::Type QSvgGradientStyle::type() const
{
return GRADIENT;
}
QSvgStyleProperty::Type QSvgTransformStyle::type() const
{
return TRANSFORM;
}
QSvgCompOpStyle::QSvgCompOpStyle(QPainter::CompositionMode mode)
: m_mode(mode)
{
}
void QSvgCompOpStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
{
m_oldMode = p->compositionMode();
p->setCompositionMode(m_mode);
}
void QSvgCompOpStyle::revert(QPainter *p, QSvgExtraStates &)
{
p->setCompositionMode(m_oldMode);
}
QSvgStyleProperty::Type QSvgCompOpStyle::type() const
{
return COMP_OP;
}
QSvgStyle::~QSvgStyle()
{
}
void QSvgStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states)
{
if (quality) {
quality->apply(p, node, states);
}
if (fill) {
fill->apply(p, node, states);
}
if (viewportFill) {
viewportFill->apply(p, node, states);
}
if (font) {
font->apply(p, node, states);
}
if (stroke) {
stroke->apply(p, node, states);
}
if (transform) {
transform->apply(p, node, states);
}
if (animateColor) {
animateColor->apply(p, node, states);
}
//animated transforms have to be applied
//_after_ the original object transformations
if (!animateTransforms.isEmpty()) {
qreal totalTimeElapsed = node->document()->currentElapsed();
// Find the last animateTransform with additive="replace", since this will override all
// previous animateTransforms.
QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constEnd();
do {
--itr;
if ((*itr)->animActive(totalTimeElapsed)
&& (*itr)->additiveType() == QSvgAnimateTransform::Replace) {
// An animateTransform with additive="replace" will replace the transform attribute.
if (transform)
transform->revert(p, states);
break;
}
} while (itr != animateTransforms.constBegin());
// Apply the animateTransforms after and including the last one with additive="replace".
for (; itr != animateTransforms.constEnd(); ++itr) {
if ((*itr)->animActive(totalTimeElapsed))
(*itr)->apply(p, node, states);
}
}
if (opacity) {
opacity->apply(p, node, states);
}
if (compop) {
compop->apply(p, node, states);
}
}
void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states)
{
if (quality) {
quality->revert(p, states);
}
if (fill) {
fill->revert(p, states);
}
if (viewportFill) {
viewportFill->revert(p, states);
}
if (font) {
font->revert(p, states);
}
if (stroke) {
stroke->revert(p, states);
}
//animated transforms need to be reverted _before_
//the native transforms
if (!animateTransforms.isEmpty()) {
QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constBegin();
for (; itr != animateTransforms.constEnd(); ++itr) {
if ((*itr)->transformApplied()) {
(*itr)->revert(p, states);
break;
}
}
for (; itr != animateTransforms.constEnd(); ++itr)
(*itr)->clearTransformApplied();
}
if (transform) {
transform->revert(p, states);
}
if (animateColor) {
animateColor->revert(p, states);
}
if (opacity) {
opacity->revert(p, states);
}
if (compop) {
compop->revert(p, states);
}
}
QSvgAnimateTransform::QSvgAnimateTransform(int startMs, int endMs, int byMs )
: QSvgStyleProperty(),
m_from(startMs),
m_totalRunningTime(endMs - startMs),
m_type(Empty),
m_additive(Replace),
m_count(0),
m_finished(false),
m_freeze(false),
m_repeatCount(-1.),
m_transformApplied(false)
{
Q_UNUSED(byMs);
}
void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector<qreal> &args)
{
m_type = type;
m_args = args;
m_additive = additive;
Q_ASSERT(!(args.count()%3));
m_count = args.count() / 3;
}
void QSvgAnimateTransform::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &)
{
m_oldWorldTransform = p->worldTransform();
resolveMatrix(node);
p->setWorldTransform(m_transform, true);
m_transformApplied = true;
}
void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &)
{
p->setWorldTransform(m_oldWorldTransform, false /* don't combine */);
m_transformApplied = false;
}
void QSvgAnimateTransform::resolveMatrix(const QSvgNode *node)
{
static const qreal deg2rad = qreal(0.017453292519943295769);
qreal totalTimeElapsed = node->document()->currentElapsed();
if (totalTimeElapsed < m_from || m_finished)
return;
qreal animationFrame = 0;
if (m_totalRunningTime != 0) {
animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
if (m_repeatCount >= 0 && m_repeatCount < animationFrame) {
m_finished = true;
animationFrame = m_repeatCount;
}
}
qreal percentOfAnimation = animationFrame;
if (percentOfAnimation > 1) {
percentOfAnimation -= ((int)percentOfAnimation);
}
qreal currentPosition = percentOfAnimation * (m_count - 1);
int endElem = qCeil(currentPosition);
int startElem = qMax(endElem - 1, 0);
switch(m_type)
{
case Translate: {
startElem *= 3;
endElem *= 3;
qreal from1, from2;
qreal to1, to2;
from1 = m_args[startElem++];
from2 = m_args[startElem++];
to1 = m_args[endElem++];
to2 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
qreal transYDiff = (to2-from2) * percentOfAnimation;
qreal transY = from2 + transYDiff;
m_transform = QTransform();
m_transform.translate(transX, transY);
break;
}
case Scale: {
startElem *= 3;
endElem *= 3;
qreal from1, from2;
qreal to1, to2;
from1 = m_args[startElem++];
from2 = m_args[startElem++];
to1 = m_args[endElem++];
to2 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
qreal transYDiff = (to2-from2) * percentOfAnimation;
qreal transY = from2 + transYDiff;
if (transY == 0)
transY = transX;
m_transform = QTransform();
m_transform.scale(transX, transY);
break;
}
case Rotate: {
startElem *= 3;
endElem *= 3;
qreal from1, from2, from3;
qreal to1, to2, to3;
from1 = m_args[startElem++];
from2 = m_args[startElem++];
from3 = m_args[startElem++];
to1 = m_args[endElem++];
to2 = m_args[endElem++];
to3 = m_args[endElem++];
qreal rotationDiff = (to1 - from1) * percentOfAnimation;
//qreal rotation = from1 + rotationDiff;
qreal transXDiff = (to2-from2) * percentOfAnimation;
qreal transX = from2 + transXDiff;
qreal transYDiff = (to3-from3) * percentOfAnimation;
qreal transY = from3 + transYDiff;
m_transform = QTransform();
m_transform.translate(transX, transY);
m_transform.rotate(rotationDiff);
m_transform.translate(-transX, -transY);
break;
}
case SkewX: {
startElem *= 3;
endElem *= 3;
qreal from1;
qreal to1;
from1 = m_args[startElem++];
to1 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
m_transform = QTransform();
m_transform.shear(qTan(transX * deg2rad), 0);
break;
}
case SkewY: {
startElem *= 3;
endElem *= 3;
qreal from1;
qreal to1;
from1 = m_args[startElem++];
to1 = m_args[endElem++];
qreal transYDiff = (to1 - from1) * percentOfAnimation;
qreal transY = from1 + transYDiff;
m_transform = QTransform();
m_transform.shear(0, qTan(transY * deg2rad));
break;
}
default:
break;
}
}
QSvgStyleProperty::Type QSvgAnimateTransform::type() const
{
return ANIMATE_TRANSFORM;
}
void QSvgAnimateTransform::setFreeze(bool freeze)
{
m_freeze = freeze;
}
void QSvgAnimateTransform::setRepeatCount(qreal repeatCount)
{
m_repeatCount = repeatCount;
}
QSvgAnimateColor::QSvgAnimateColor(int startMs, int endMs, int byMs)
: QSvgStyleProperty(),
m_from(startMs),
m_totalRunningTime(endMs - startMs),
m_fill(false),
m_finished(false),
m_freeze(false),
m_repeatCount(-1.)
{
Q_UNUSED(byMs);
}
void QSvgAnimateColor::setArgs(bool fill,
const QList<QColor> &colors)
{
m_fill = fill;
m_colors = colors;
}
void QSvgAnimateColor::setFreeze(bool freeze)
{
m_freeze = freeze;
}
void QSvgAnimateColor::setRepeatCount(qreal repeatCount)
{
m_repeatCount = repeatCount;
}
void QSvgAnimateColor::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &)
{
qreal totalTimeElapsed = node->document()->currentElapsed();
if (totalTimeElapsed < m_from || m_finished)
return;
qreal animationFrame = 0;
if (m_totalRunningTime != 0)
animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
if (m_repeatCount >= 0 && m_repeatCount < animationFrame) {
m_finished = true;
animationFrame = m_repeatCount;
}
qreal percentOfAnimation = animationFrame;
if (percentOfAnimation > 1) {
percentOfAnimation -= ((int)percentOfAnimation);
}
qreal currentPosition = percentOfAnimation * (m_colors.count() - 1);
int startElem = qFloor(currentPosition);
int endElem = qCeil(currentPosition);
QColor start = m_colors[startElem];
QColor end = m_colors[endElem];
qreal percentOfColorMorph = currentPosition;
if (percentOfColorMorph > 1) {
percentOfColorMorph -= ((int)percentOfColorMorph);
}
// Interpolate between the two fixed colors start and end
qreal aDiff = (end.alpha() - start.alpha()) * percentOfColorMorph;
qreal rDiff = (end.red() - start.red()) * percentOfColorMorph;
qreal gDiff = (end.green() - start.green()) * percentOfColorMorph;
qreal bDiff = (end.blue() - start.blue()) * percentOfColorMorph;
int alpha = int(start.alpha() + aDiff);
int red = int(start.red() + rDiff);
int green = int(start.green() + gDiff);
int blue = int(start.blue() + bDiff);
QColor color(red, green, blue, alpha);
if (m_fill) {
QBrush b = p->brush();
m_oldBrush = b;
b.setColor(color);
p->setBrush(b);
} else {
QPen pen = p->pen();
m_oldPen = pen;
pen.setColor(color);
p->setPen(pen);
}
}
void QSvgAnimateColor::revert(QPainter *p, QSvgExtraStates &)
{
if (m_fill) {
p->setBrush(m_oldBrush);
} else {
p->setPen(m_oldPen);
}
}
QSvgStyleProperty::Type QSvgAnimateColor::type() const
{
return ANIMATE_COLOR;
}
QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity)
: m_opacity(opacity), m_oldOpacity(0)
{
}
void QSvgOpacityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
{
m_oldOpacity = p->opacity();
p->setOpacity(m_opacity * m_oldOpacity);
}
void QSvgOpacityStyle::revert(QPainter *p, QSvgExtraStates &)
{
p->setOpacity(m_oldOpacity);
}
QSvgStyleProperty::Type QSvgOpacityStyle::type() const
{
return OPACITY;
}
void QSvgGradientStyle::setStopLink(const QString &link, QSvgTinyDocument *doc)
{
m_link = link;
m_doc = doc;
}
void QSvgGradientStyle::resolveStops()
{
QStringList visited;
resolveStops_helper(&visited);
}
void QSvgGradientStyle::resolveStops_helper(QStringList *visited)
{
if (!m_link.isEmpty() && m_doc) {
QSvgStyleProperty *prop = m_doc->styleProperty(m_link);
if (prop && !visited->contains(m_link)) {
visited->append(m_link);
if (prop->type() == QSvgStyleProperty::GRADIENT) {
QSvgGradientStyle *st =
static_cast<QSvgGradientStyle*>(prop);
st->resolveStops_helper(visited);
m_gradient->setStops(st->qgradient()->stops());
m_gradientStopsSet = st->gradientStopsSet();
}
} else {
qWarning("Could not resolve property : %s", qPrintable(m_link));
}
m_link = QString();
}
}
QT_END_NAMESPACE

822
svg/qsvgstyle_p.h Normal file
View File

@ -0,0 +1,822 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGSTYLE_P_H
#define QSVGSTYLE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtGui/qpainter.h"
#include "QtGui/qpen.h"
#include "QtGui/qbrush.h"
#include "QtGui/qmatrix.h"
#include "QtGui/qcolor.h"
#include "QtGui/qfont.h"
#include <qdebug.h>
#include "qtsvgglobal_p.h"
QT_BEGIN_NAMESPACE
class QPainter;
class QSvgNode;
class QSvgFont;
class QSvgTinyDocument;
template <class T> class QSvgRefCounter
{
public:
QSvgRefCounter() { t = 0; }
QSvgRefCounter(T *_t)
{
t = _t;
if (t)
t->ref();
}
QSvgRefCounter(const QSvgRefCounter &other)
{
t = other.t;
if (t)
t->ref();
}
QSvgRefCounter &operator =(T *_t)
{
if(_t)
_t->ref();
if (t)
t->deref();
t = _t;
return *this;
}
QSvgRefCounter &operator =(const QSvgRefCounter &other)
{
if(other.t)
other.t->ref();
if (t)
t->deref();
t = other.t;
return *this;
}
~QSvgRefCounter()
{
if (t)
t->deref();
}
inline T *operator->() const { return t; }
inline operator T*() const { return t; }
private:
T *t;
};
class Q_SVG_PRIVATE_EXPORT QSvgRefCounted
{
public:
QSvgRefCounted() { _ref = 0; }
virtual ~QSvgRefCounted() {}
void ref() {
++_ref;
// qDebug() << this << ": adding ref, now " << _ref;
}
void deref() {
// qDebug() << this << ": removing ref, now " << _ref;
if(!--_ref) {
// qDebug(" deleting");
delete this;
}
}
private:
int _ref;
};
struct Q_SVG_PRIVATE_EXPORT QSvgExtraStates
{
QSvgExtraStates();
qreal fillOpacity;
qreal strokeOpacity;
QSvgFont *svgFont;
Qt::Alignment textAnchor;
int fontWeight;
Qt::FillRule fillRule;
qreal strokeDashOffset;
bool vectorEffect; // true if pen is cosmetic
};
class Q_SVG_PRIVATE_EXPORT QSvgStyleProperty : public QSvgRefCounted
{
public:
enum Type
{
QUALITY,
FILL,
VIEWPORT_FILL,
FONT,
STROKE,
SOLID_COLOR,
GRADIENT,
TRANSFORM,
ANIMATE_TRANSFORM,
ANIMATE_COLOR,
OPACITY,
COMP_OP
};
public:
virtual ~QSvgStyleProperty();
virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0;
virtual void revert(QPainter *p, QSvgExtraStates &states) =0;
virtual Type type() const=0;
};
class Q_SVG_PRIVATE_EXPORT QSvgFillStyleProperty : public QSvgStyleProperty
{
public:
virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0;
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
};
class Q_SVG_PRIVATE_EXPORT QSvgQualityStyle : public QSvgStyleProperty
{
public:
QSvgQualityStyle(int color);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
private:
// color-render ing v v 'auto' | 'optimizeSpeed' |
// 'optimizeQuality' | 'inherit'
//int m_colorRendering;
// shape-rendering v v 'auto' | 'optimizeSpeed' | 'crispEdges' |
// 'geometricPrecision' | 'inherit'
//QSvgShapeRendering m_shapeRendering;
// text-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeLegibility'
// | 'geometricPrecision' | 'inherit'
//QSvgTextRendering m_textRendering;
// vector-effect v x 'default' | 'non-scaling-stroke' | 'inherit'
//QSvgVectorEffect m_vectorEffect;
// image-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeQuality' |
// 'inherit'
//QSvgImageRendering m_imageRendering;
};
class Q_SVG_PRIVATE_EXPORT QSvgOpacityStyle : public QSvgStyleProperty
{
public:
QSvgOpacityStyle(qreal opacity);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
private:
qreal m_opacity;
qreal m_oldOpacity;
};
class Q_SVG_PRIVATE_EXPORT QSvgFillStyle : public QSvgStyleProperty
{
public:
QSvgFillStyle();
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
void setFillRule(Qt::FillRule f);
void setFillOpacity(qreal opacity);
void setFillStyle(QSvgFillStyleProperty* style);
void setBrush(QBrush brush);
const QBrush & qbrush() const
{
return m_fill;
}
qreal fillOpacity() const
{
return m_fillOpacity;
}
Qt::FillRule fillRule() const
{
return m_fillRule;
}
QSvgFillStyleProperty* style() const
{
return m_style;
}
void setGradientId(const QString &Id)
{
m_gradientId = Id;
}
QString gradientId() const
{
return m_gradientId;
}
void setGradientResolved(bool resolved)
{
m_gradientResolved = resolved;
}
bool isGradientResolved() const
{
return m_gradientResolved;
}
private:
// fill v v 'inherit' | <Paint.datatype>
// fill-opacity v v 'inherit' | <OpacityValue.datatype>
QBrush m_fill;
QBrush m_oldFill;
QSvgFillStyleProperty *m_style;
Qt::FillRule m_fillRule;
Qt::FillRule m_oldFillRule;
qreal m_fillOpacity;
qreal m_oldFillOpacity;
QString m_gradientId;
uint m_gradientResolved : 1;
uint m_fillRuleSet : 1;
uint m_fillOpacitySet : 1;
uint m_fillSet : 1;
};
class Q_SVG_PRIVATE_EXPORT QSvgViewportFillStyle : public QSvgStyleProperty
{
public:
QSvgViewportFillStyle(const QBrush &brush);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
const QBrush & qbrush() const
{
return m_viewportFill;
}
private:
// viewport-fill v x 'inherit' | <Paint.datatype>
// viewport-fill-opacity v x 'inherit' | <OpacityValue.datatype>
QBrush m_viewportFill;
QBrush m_oldFill;
};
class Q_SVG_PRIVATE_EXPORT QSvgFontStyle : public QSvgStyleProperty
{
public:
static const int LIGHTER = -1;
static const int BOLDER = 1;
QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc);
QSvgFontStyle();
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
void setSize(qreal size)
{
// Store the _pixel_ size in the font. Since QFont::setPixelSize() only takes an int, call
// QFont::SetPointSize() instead. Set proper font size just before rendering.
m_qfont.setPointSizeF(size);
m_sizeSet = 1;
}
void setTextAnchor(Qt::Alignment anchor)
{
m_textAnchor = anchor;
m_textAnchorSet = 1;
}
void setFamily(const QString &family)
{
m_qfont.setFamily(family);
m_familySet = 1;
}
void setStyle(QFont::Style fontStyle) {
m_qfont.setStyle(fontStyle);
m_styleSet = 1;
}
void setVariant(QFont::Capitalization fontVariant)
{
m_qfont.setCapitalization(fontVariant);
m_variantSet = 1;
}
static int SVGToQtWeight(int weight);
void setWeight(int weight)
{
m_weight = weight;
m_weightSet = 1;
}
QSvgFont * svgFont() const
{
return m_svgFont;
}
const QFont &qfont() const
{
return m_qfont;
}
QSvgTinyDocument *doc() const {return m_doc;}
private:
QSvgFont *m_svgFont;
QSvgTinyDocument *m_doc;
QFont m_qfont;
int m_weight;
Qt::Alignment m_textAnchor;
QSvgFont *m_oldSvgFont;
QFont m_oldQFont;
Qt::Alignment m_oldTextAnchor;
int m_oldWeight;
uint m_familySet : 1;
uint m_sizeSet : 1;
uint m_styleSet : 1;
uint m_variantSet : 1;
uint m_weightSet : 1;
uint m_textAnchorSet : 1;
};
class Q_SVG_PRIVATE_EXPORT QSvgStrokeStyle : public QSvgStyleProperty
{
public:
QSvgStrokeStyle();
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
void setStroke(QBrush brush)
{
m_stroke.setBrush(brush);
m_style = 0;
m_strokeSet = 1;
}
void setStyle(QSvgFillStyleProperty *style)
{
m_style = style;
m_strokeSet = 1;
}
void setDashArray(const QVector<qreal> &dashes);
void setDashArrayNone()
{
m_stroke.setStyle(Qt::SolidLine);
m_strokeDashArraySet = 1;
}
void setDashOffset(qreal offset)
{
m_strokeDashOffset = offset;
m_strokeDashOffsetSet = 1;
}
void setLineCap(Qt::PenCapStyle cap)
{
m_stroke.setCapStyle(cap);
m_strokeLineCapSet = 1;
}
void setLineJoin(Qt::PenJoinStyle join)
{
m_stroke.setJoinStyle(join);
m_strokeLineJoinSet = 1;
}
void setMiterLimit(qreal limit)
{
m_stroke.setMiterLimit(limit);
m_strokeMiterLimitSet = 1;
}
void setOpacity(qreal opacity)
{
m_strokeOpacity = opacity;
m_strokeOpacitySet = 1;
}
void setWidth(qreal width)
{
m_stroke.setWidthF(width);
m_strokeWidthSet = 1;
Q_ASSERT(!m_strokeDashArraySet); // set width before dash array.
}
qreal width()
{
return m_stroke.widthF();
}
void setVectorEffect(bool nonScalingStroke)
{
m_vectorEffect = nonScalingStroke;
m_vectorEffectSet = 1;
}
QSvgFillStyleProperty* style() const
{
return m_style;
}
void setGradientId(const QString &Id)
{
m_gradientId = Id;
}
QString gradientId() const
{
return m_gradientId;
}
void setGradientResolved(bool resolved)
{
m_gradientResolved = resolved;
}
bool isGradientResolved() const
{
return m_gradientResolved;
}
QPen stroke() const
{
return m_stroke;
}
private:
// stroke v v 'inherit' | <Paint.datatype>
// stroke-dasharray v v 'inherit' | <StrokeDashArrayValue.datatype>
// stroke-dashoffset v v 'inherit' | <StrokeDashOffsetValue.datatype>
// stroke-linecap v v 'butt' | 'round' | 'square' | 'inherit'
// stroke-linejoin v v 'miter' | 'round' | 'bevel' | 'inherit'
// stroke-miterlimit v v 'inherit' | <StrokeMiterLimitValue.datatype>
// stroke-opacity v v 'inherit' | <OpacityValue.datatype>
// stroke-width v v 'inherit' | <StrokeWidthValue.datatype>
QPen m_stroke;
QPen m_oldStroke;
qreal m_strokeOpacity;
qreal m_oldStrokeOpacity;
qreal m_strokeDashOffset;
qreal m_oldStrokeDashOffset;
QSvgFillStyleProperty *m_style;
QString m_gradientId;
uint m_gradientResolved : 1;
uint m_vectorEffect : 1;
uint m_oldVectorEffect : 1;
uint m_strokeSet : 1;
uint m_strokeDashArraySet : 1;
uint m_strokeDashOffsetSet : 1;
uint m_strokeLineCapSet : 1;
uint m_strokeLineJoinSet : 1;
uint m_strokeMiterLimitSet : 1;
uint m_strokeOpacitySet : 1;
uint m_strokeWidthSet : 1;
uint m_vectorEffectSet : 1;
};
class Q_SVG_PRIVATE_EXPORT QSvgSolidColorStyle : public QSvgFillStyleProperty
{
public:
QSvgSolidColorStyle(const QColor &color);
Type type() const override;
const QColor & qcolor() const
{
return m_solidColor;
}
QBrush brush(QPainter *, QSvgExtraStates &) override
{
return m_solidColor;
}
private:
// solid-color v x 'inherit' | <SVGColor.datatype>
// solid-opacity v x 'inherit' | <OpacityValue.datatype>
QColor m_solidColor;
QBrush m_oldFill;
QPen m_oldStroke;
};
class Q_SVG_PRIVATE_EXPORT QSvgGradientStyle : public QSvgFillStyleProperty
{
public:
QSvgGradientStyle(QGradient *grad);
~QSvgGradientStyle() { delete m_gradient; }
Type type() const override;
void setStopLink(const QString &link, QSvgTinyDocument *doc);
QString stopLink() const { return m_link; }
void resolveStops();
void resolveStops_helper(QStringList *visited);
void setMatrix(const QMatrix &matrix);
QMatrix qmatrix() const
{
return m_matrix;
}
QGradient *qgradient() const
{
return m_gradient;
}
bool gradientStopsSet() const
{
return m_gradientStopsSet;
}
void setGradientStopsSet(bool set)
{
m_gradientStopsSet = set;
}
QBrush brush(QPainter *, QSvgExtraStates &) override;
private:
QGradient *m_gradient;
QMatrix m_matrix;
QSvgTinyDocument *m_doc;
QString m_link;
bool m_gradientStopsSet;
};
class Q_SVG_PRIVATE_EXPORT QSvgTransformStyle : public QSvgStyleProperty
{
public:
QSvgTransformStyle(const QTransform &transform);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
const QTransform & qtransform() const
{
return m_transform;
}
private:
//7.6 The transform attribute
QTransform m_transform;
QTransform m_oldWorldTransform;
};
class Q_SVG_PRIVATE_EXPORT QSvgAnimateTransform : public QSvgStyleProperty
{
public:
enum TransformType
{
Empty,
Translate,
Scale,
Rotate,
SkewX,
SkewY
};
enum Additive
{
Sum,
Replace
};
public:
QSvgAnimateTransform(int startMs, int endMs, int by = 0);
void setArgs(TransformType type, Additive additive, const QVector<qreal> &args);
void setFreeze(bool freeze);
void setRepeatCount(qreal repeatCount);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
QSvgAnimateTransform::Additive additiveType() const
{
return m_additive;
}
bool animActive(qreal totalTimeElapsed)
{
if (totalTimeElapsed < m_from)
return false;
if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite"
return true;
if (m_totalRunningTime == 0)
return false;
qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
if (animationFrame > m_repeatCount)
return false;
return true;
}
bool transformApplied() const
{
return m_transformApplied;
}
// Call this instead of revert if you know that revert is unnecessary.
void clearTransformApplied()
{
m_transformApplied = false;
}
protected:
void resolveMatrix(const QSvgNode *node);
private:
qreal m_from;
qreal m_totalRunningTime;
TransformType m_type;
Additive m_additive;
QVector<qreal> m_args;
int m_count;
QTransform m_transform;
QTransform m_oldWorldTransform;
bool m_finished;
bool m_freeze;
qreal m_repeatCount;
bool m_transformApplied;
};
class Q_SVG_PRIVATE_EXPORT QSvgAnimateColor : public QSvgStyleProperty
{
public:
QSvgAnimateColor(int startMs, int endMs, int by = 0);
void setArgs(bool fill, const QList<QColor> &colors);
void setFreeze(bool freeze);
void setRepeatCount(qreal repeatCount);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
private:
qreal m_from;
qreal m_totalRunningTime;
QList<QColor> m_colors;
QBrush m_oldBrush;
QPen m_oldPen;
bool m_fill;
bool m_finished;
bool m_freeze;
qreal m_repeatCount;
};
class Q_SVG_PRIVATE_EXPORT QSvgCompOpStyle : public QSvgStyleProperty
{
public:
QSvgCompOpStyle(QPainter::CompositionMode mode);
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
void revert(QPainter *p, QSvgExtraStates &states) override;
Type type() const override;
const QPainter::CompositionMode & compOp() const
{
return m_mode;
}
private:
//comp-op attribute
QPainter::CompositionMode m_mode;
QPainter::CompositionMode m_oldMode;
};
class Q_SVG_PRIVATE_EXPORT QSvgStyle
{
public:
QSvgStyle()
: quality(0),
fill(0),
viewportFill(0),
font(0),
stroke(0),
solidColor(0),
gradient(0),
transform(0),
animateColor(0),
opacity(0),
compop(0)
{}
~QSvgStyle();
void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states);
void revert(QPainter *p, QSvgExtraStates &states);
QSvgRefCounter<QSvgQualityStyle> quality;
QSvgRefCounter<QSvgFillStyle> fill;
QSvgRefCounter<QSvgViewportFillStyle> viewportFill;
QSvgRefCounter<QSvgFontStyle> font;
QSvgRefCounter<QSvgStrokeStyle> stroke;
QSvgRefCounter<QSvgSolidColorStyle> solidColor;
QSvgRefCounter<QSvgGradientStyle> gradient;
QSvgRefCounter<QSvgTransformStyle> transform;
QSvgRefCounter<QSvgAnimateColor> animateColor;
QList<QSvgRefCounter<QSvgAnimateTransform> > animateTransforms;
QSvgRefCounter<QSvgOpacityStyle> opacity;
QSvgRefCounter<QSvgCompOpStyle> compop;
};
/********************************************************/
// NOT implemented:
// color v v 'inherit' | <Color.datatype>
//QColor m_color;
// display v x 'inline' | 'block' | 'list-item'
// | 'run-in' | 'compact' | 'marker' |
// 'table' | 'inline-table' |
// 'table-row-group' | 'table-header-group' |
// 'table-footer-group' | 'table-row' |
// 'table-column-group' | 'table-column' |
// 'table-cell' | 'table-caption' |
// 'none' | 'inherit'
//QSvgDisplayStyle m_display;
// display-align v v 'auto' | 'before' | 'center' | 'after' | 'inherit'
//QSvgDisplayAlign m_displayAlign;
// line-increment v v 'auto' | 'inherit' | <Number.datatype>
//int m_lineIncrement;
// text-anchor v v 'start' | 'middle' | 'end' | 'inherit'
//QSvgTextAnchor m_textAnchor;
// visibility v v 'visible' | 'hidden' | 'inherit'
//QSvgVisibility m_visibility;
/******************************************************/
// the following do not make sense for us
// pointer-events v v 'visiblePainted' | 'visibleFill' | 'visibleStroke' |
// 'visible' | 'painted' | 'fill' | 'stroke' | 'all' |
// 'none' | 'inherit'
//QSvgPointEvents m_pointerEvents;
// audio-level v x 'inherit' | <Number.datatype>
QT_END_NAMESPACE
#endif // QSVGSTYLE_P_H

557
svg/qsvgtinydocument.cpp Normal file
View File

@ -0,0 +1,557 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgtinydocument_p.h"
#include "qsvghandler_p.h"
#include "qsvgfont_p.h"
#include "qpainter.h"
#include "qfile.h"
#include "qbuffer.h"
#include "qbytearray.h"
#include "qqueue.h"
#include "qstack.h"
#include "qdebug.h"
#ifndef QT_NO_COMPRESS
#include <zlib.h>
#endif
QT_BEGIN_NAMESPACE
QSvgTinyDocument::QSvgTinyDocument()
: QSvgStructureNode(0)
, m_widthPercent(false)
, m_heightPercent(false)
, m_animated(false)
, m_animationDuration(0)
, m_fps(30)
{
}
QSvgTinyDocument::~QSvgTinyDocument()
{
}
#ifndef QT_NO_COMPRESS
# ifdef QT_BUILD_INTERNAL
Q_AUTOTEST_EXPORT QByteArray qt_inflateGZipDataFrom(QIODevice *device);
# else
static QByteArray qt_inflateGZipDataFrom(QIODevice *device);
# endif
QByteArray qt_inflateGZipDataFrom(QIODevice *device)
{
if (!device)
return QByteArray();
if (!device->isOpen())
device->open(QIODevice::ReadOnly);
Q_ASSERT(device->isOpen() && device->isReadable());
static const int CHUNK_SIZE = 4096;
int zlibResult = Z_OK;
QByteArray source;
QByteArray destination;
// Initialize zlib stream struct
z_stream zlibStream;
zlibStream.next_in = Z_NULL;
zlibStream.avail_in = 0;
zlibStream.avail_out = 0;
zlibStream.zalloc = Z_NULL;
zlibStream.zfree = Z_NULL;
zlibStream.opaque = Z_NULL;
// Adding 16 to the window size gives us gzip decoding
if (inflateInit2(&zlibStream, MAX_WBITS + 16) != Z_OK) {
qCWarning(lcSvgHandler, "Cannot initialize zlib, because: %s",
(zlibStream.msg != NULL ? zlibStream.msg : "Unknown error"));
return QByteArray();
}
bool stillMoreWorkToDo = true;
while (stillMoreWorkToDo) {
if (!zlibStream.avail_in) {
source = device->read(CHUNK_SIZE);
if (source.isEmpty())
break;
zlibStream.avail_in = source.size();
zlibStream.next_in = reinterpret_cast<Bytef*>(source.data());
}
do {
// Prepare the destination buffer
int oldSize = destination.size();
destination.resize(oldSize + CHUNK_SIZE);
zlibStream.next_out = reinterpret_cast<Bytef*>(
destination.data() + oldSize - zlibStream.avail_out);
zlibStream.avail_out += CHUNK_SIZE;
zlibResult = inflate(&zlibStream, Z_NO_FLUSH);
switch (zlibResult) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_STREAM_ERROR:
case Z_MEM_ERROR: {
inflateEnd(&zlibStream);
qCWarning(lcSvgHandler, "Error while inflating gzip file: %s",
(zlibStream.msg != NULL ? zlibStream.msg : "Unknown error"));
destination.chop(zlibStream.avail_out);
return destination;
}
}
// If the output buffer still has more room after calling inflate
// it means we have to provide more data, so exit the loop here
} while (!zlibStream.avail_out);
if (zlibResult == Z_STREAM_END) {
// Make sure there are no more members to process before exiting
if (!(zlibStream.avail_in && inflateReset(&zlibStream) == Z_OK))
stillMoreWorkToDo = false;
}
}
// Chop off trailing space in the buffer
destination.chop(zlibStream.avail_out);
inflateEnd(&zlibStream);
return destination;
}
#endif
QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly)) {
qCWarning(lcSvgHandler, "Cannot open file '%s', because: %s",
qPrintable(fileName), qPrintable(file.errorString()));
return 0;
}
#ifndef QT_NO_COMPRESS
if (fileName.endsWith(QLatin1String(".svgz"), Qt::CaseInsensitive)
|| fileName.endsWith(QLatin1String(".svg.gz"), Qt::CaseInsensitive)) {
return load(qt_inflateGZipDataFrom(&file));
}
#endif
QSvgTinyDocument *doc = 0;
QSvgHandler handler(&file);
if (handler.ok()) {
doc = handler.document();
doc->m_animationDuration = handler.animationDuration();
} else {
qCWarning(lcSvgHandler, "Cannot read file '%s', because: %s (line %d)",
qPrintable(fileName), qPrintable(handler.errorString()), handler.lineNumber());
delete handler.document();
}
return doc;
}
QSvgTinyDocument * QSvgTinyDocument::load(const QByteArray &contents)
{
#ifndef QT_NO_COMPRESS
// Check for gzip magic number and inflate if appropriate
if (contents.startsWith("\x1f\x8b")) {
QBuffer buffer(const_cast<QByteArray *>(&contents));
return load(qt_inflateGZipDataFrom(&buffer));
}
#endif
QSvgHandler handler(contents);
QSvgTinyDocument *doc = 0;
if (handler.ok()) {
doc = handler.document();
doc->m_animationDuration = handler.animationDuration();
} else {
delete handler.document();
}
return doc;
}
QSvgTinyDocument * QSvgTinyDocument::load(QXmlStreamReader *contents)
{
QSvgHandler handler(contents);
QSvgTinyDocument *doc = 0;
if (handler.ok()) {
doc = handler.document();
doc->m_animationDuration = handler.animationDuration();
} else {
delete handler.document();
}
return doc;
}
void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
{
if (m_time.isNull()) {
m_time.start();
}
if (displayMode() == QSvgNode::NoneMode)
return;
p->save();
//sets default style on the painter
//### not the most optimal way
QTransform oldTransform = p->worldTransform();
mapSourceToTarget(p, bounds);
QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin);
pen.setMiterLimit(4);
p->setPen(pen);
p->setBrush(Qt::black);
p->setRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::SmoothPixmapTransform);
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, m_states);
while (itr != m_renderers.end()) {
QSvgNode *node = *itr;
if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) {
QSvgText *a = dynamic_cast<QSvgText*>(node);
if(a) {
QVector<QSvgTspan *> &ts=a->Tspans();
int s=0;
if(ts.size()){
QString st=ts[0]->text();
if(st.indexOf('$')>=0) {
s=1;
}
}
/*if(!s) {
a->draw(p,m_states);
}
else*/
{
p->save();
QRectF source = viewBox();
QMatrix b=matrixForElement(a);
a->draw(p,m_states,bounds,oldTransform,source,b);
p->restore();
}
}
else
{
QSvgRect *a = dynamic_cast<QSvgRect*>(node);
if(a) {
QRectF source = viewBox();
QRectF rect=a->rect();
qreal sx=rect.width()/source.width();
qreal sy=rect.height()/source.height();
qreal x0=(rect.x()-source.x())/source.width();
qreal y0=(rect.y()-source.y())/source.height();
QRectF mRect(bounds.x()+x0*bounds.width(),bounds.y()+y0*bounds.height(),bounds.width()*sx,bounds.height()*sy);
p->save();
p->setWorldTransform(oldTransform);
QRectF trect=p->transform().mapRect(mRect);
p->setWorldTransform(QTransform());//临时切回像素坐标系
a->SetRect(trect);
node->draw(p,m_states);
p->restore();
}
else
node->draw(p, m_states);
}
}
++itr;
}
revertStyle(p, m_states);
p->restore();
}
void QSvgTinyDocument::draw(QPainter *p, const QString &id,
const QRectF &bounds)
{
QSvgNode *node = scopeNode(id);
if (!node) {
qCDebug(lcSvgHandler, "Couldn't find node %s. Skipping rendering.", qPrintable(id));
return;
}
if (m_time.isNull()) {
m_time.start();
}
if (node->displayMode() == QSvgNode::NoneMode)
return;
p->save();
const QRectF elementBounds = node->transformedBounds();
mapSourceToTarget(p, bounds, elementBounds);
QTransform originalTransform = p->worldTransform();
//XXX set default style on the painter
QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin);
pen.setMiterLimit(4);
p->setPen(pen);
p->setBrush(Qt::black);
p->setRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::SmoothPixmapTransform);
QStack<QSvgNode*> parentApplyStack;
QSvgNode *parent = node->parent();
while (parent) {
parentApplyStack.push(parent);
parent = parent->parent();
}
for (int i = parentApplyStack.size() - 1; i >= 0; --i)
parentApplyStack[i]->applyStyle(p, m_states);
// Reset the world transform so that our parents don't affect
// the position
QTransform currentTransform = p->worldTransform();
p->setWorldTransform(originalTransform);
node->draw(p, m_states);
p->setWorldTransform(currentTransform);
for (int i = 0; i < parentApplyStack.size(); ++i)
parentApplyStack[i]->revertStyle(p, m_states);
//p->fillRect(bounds.adjusted(-5, -5, 5, 5), QColor(0, 0, 255, 100));
p->restore();
}
QSvgNode::Type QSvgTinyDocument::type() const
{
return DOC;
}
void QSvgTinyDocument::setWidth(int len, bool percent)
{
m_size.setWidth(len);
m_widthPercent = percent;
}
void QSvgTinyDocument::setHeight(int len, bool percent)
{
m_size.setHeight(len);
m_heightPercent = percent;
}
void QSvgTinyDocument::setViewBox(const QRectF &rect)
{
m_viewBox = rect;
}
void QSvgTinyDocument::addSvgFont(QSvgFont *font)
{
m_fonts.insert(font->familyName(), font);
}
QSvgFont * QSvgTinyDocument::svgFont(const QString &family) const
{
return m_fonts[family];
}
void QSvgTinyDocument::addNamedNode(const QString &id, QSvgNode *node)
{
m_namedNodes.insert(id, node);
}
QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const
{
return m_namedNodes.value(id);
}
void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style)
{
if (!m_namedStyles.contains(id))
m_namedStyles.insert(id, style);
else
qCWarning(lcSvgHandler) << "Duplicate unique style id:" << id;
}
QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const
{
return m_namedStyles.value(id);
}
void QSvgTinyDocument::restartAnimation()
{
m_time.restart();
}
bool QSvgTinyDocument::animated() const
{
return m_animated;
}
void QSvgTinyDocument::setAnimated(bool a)
{
m_animated = a;
}
void QSvgTinyDocument::draw(QPainter *p)
{
draw(p, QRectF());
}
void QSvgTinyDocument::draw(QPainter *p, QSvgExtraStates &)
{
draw(p);
}
void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect, const QRectF &sourceRect)
{
QRectF target = targetRect;
if (target.isNull()) {
QPaintDevice *dev = p->device();
QRectF deviceRect(0, 0, dev->width(), dev->height());
if (deviceRect.isNull()) {
if (sourceRect.isNull())
target = QRectF(QPointF(0, 0), size());
else
target = QRectF(QPointF(0, 0), sourceRect.size());
} else {
target = deviceRect;
}
}
QRectF source = sourceRect;
if (source.isNull())
source = viewBox();
if (source != target && !source.isNull()) {
QTransform transform;
transform.scale(target.width() / source.width(),
target.height() / source.height());
QRectF c2 = transform.mapRect(source);
float x1=target.x();
float y1=target.y();
float x2=c2.x();
float y2=c2.y();
p->translate(target.x() - c2.x(),
target.y() - c2.y());
p->scale(target.width() / source.width(),
target.height() / source.height());
}
}
QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const
{
const QSvgNode *node = scopeNode(id);
if (!node)
node = this;
return node->transformedBounds();
}
bool QSvgTinyDocument::elementExists(const QString &id) const
{
QSvgNode *node = scopeNode(id);
return (node!=0);
}
QMatrix QSvgTinyDocument::matrixForElement(const QString &id) const
{
QSvgNode *node = scopeNode(id);
if (!node) {
qCDebug(lcSvgHandler, "Couldn't find node %s. Skipping rendering.", qPrintable(id));
return QMatrix();
}
QTransform t;
node = node->parent();
while (node) {
if (node->m_style.transform)
t *= node->m_style.transform->qtransform();
node = node->parent();
}
return t.toAffine();
}
QMatrix QSvgTinyDocument::matrixForElement(QSvgNode *node) const
{
if (!node) {
qDebug("Couldn't find node %s. Skipping rendering.", "node");
return QMatrix();
}
QTransform t;
if (node->m_style.transform)
t = node->m_style.transform->qtransform();
return t.toAffine();
}
int QSvgTinyDocument::currentFrame() const
{
double runningPercentage = qMin(m_time.elapsed()/double(m_animationDuration), 1.);
int totalFrames = m_fps * m_animationDuration;
return int(runningPercentage * totalFrames);
}
void QSvgTinyDocument::setCurrentFrame(int frame)
{
int totalFrames = m_fps * m_animationDuration;
double framePercentage = frame/double(totalFrames);
double timeForFrame = m_animationDuration * framePercentage; //in S
timeForFrame *= 1000; //in ms
int timeToAdd = int(timeForFrame - m_time.elapsed());
m_time = m_time.addMSecs(timeToAdd);
}
void QSvgTinyDocument::setFramesPerSecond(int num)
{
m_fps = num;
}
QT_END_NAMESPACE

201
svg/qsvgtinydocument_p.h Normal file
View File

@ -0,0 +1,201 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGTINYDOCUMENT_P_H
#define QSVGTINYDOCUMENT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsvgstructure_p.h"
#include "qtsvgglobal_p.h"
#include "QtCore/qrect.h"
#include "QtCore/qlist.h"
#include "QtCore/qhash.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qxmlstream.h"
#include "qsvgstyle_p.h"
#include "qsvgfont_p.h"
QT_BEGIN_NAMESPACE
class QPainter;
class QByteArray;
class QSvgFont;
class Q_SVG_PRIVATE_EXPORT QSvgTinyDocument : public QSvgStructureNode
{
public:
static QSvgTinyDocument * load(const QString &file);
static QSvgTinyDocument * load(const QByteArray &contents);
static QSvgTinyDocument * load(QXmlStreamReader *contents);
public:
QSvgTinyDocument();
~QSvgTinyDocument();
Type type() const override;
QSize size() const;
void setWidth(int len, bool percent);
void setHeight(int len, bool percent);
int width() const;
int height() const;
bool widthPercent() const;
bool heightPercent() const;
bool preserveAspectRatio() const;
QRectF viewBox() const;
void setViewBox(const QRectF &rect);
void draw(QPainter *p, QSvgExtraStates &) override; //from the QSvgNode
void draw(QPainter *p);
void draw(QPainter *p, const QRectF &bounds);
void draw(QPainter *p, const QString &id,
const QRectF &bounds=QRectF());
QMatrix matrixForElement(const QString &id) const;
QRectF boundsOnElement(const QString &id) const;
bool elementExists(const QString &id) const;
void addSvgFont(QSvgFont *);
QSvgFont *svgFont(const QString &family) const;
void addNamedNode(const QString &id, QSvgNode *node);
QSvgNode *namedNode(const QString &id) const;
void addNamedStyle(const QString &id, QSvgFillStyleProperty *style);
QSvgFillStyleProperty *namedStyle(const QString &id) const;
void restartAnimation();
int currentElapsed() const;
bool animated() const;
void setAnimated(bool a);
int animationDuration() const;
int currentFrame() const;
void setCurrentFrame(int);
void setFramesPerSecond(int num);
private:
void mapSourceToTarget(QPainter *p, const QRectF &targetRect, const QRectF &sourceRect = QRectF());
private:
QSize m_size;
bool m_widthPercent;
bool m_heightPercent;
mutable QRectF m_viewBox;
QHash<QString, QSvgRefCounter<QSvgFont> > m_fonts;
QHash<QString, QSvgNode *> m_namedNodes;
QHash<QString, QSvgRefCounter<QSvgFillStyleProperty> > m_namedStyles;
QTime m_time;
bool m_animated;
int m_animationDuration;
int m_fps;
QSvgExtraStates m_states;
public:
QMatrix matrixForElement(QSvgNode *node) const;
};
inline QSize QSvgTinyDocument::size() const
{
if (m_size.isEmpty())
return viewBox().size().toSize();
if (m_widthPercent || m_heightPercent) {
const int width = m_widthPercent ? qRound(0.01 * m_size.width() * viewBox().size().width()) : m_size.width();
const int height = m_heightPercent ? qRound(0.01 * m_size.height() * viewBox().size().height()) : m_size.height();
return QSize(width, height);
}
return m_size;
}
inline int QSvgTinyDocument::width() const
{
return size().width();
}
inline int QSvgTinyDocument::height() const
{
return size().height();
}
inline bool QSvgTinyDocument::widthPercent() const
{
return m_widthPercent;
}
inline bool QSvgTinyDocument::heightPercent() const
{
return m_heightPercent;
}
inline QRectF QSvgTinyDocument::viewBox() const
{
if (m_viewBox.isNull())
m_viewBox = transformedBounds();
return m_viewBox;
}
inline bool QSvgTinyDocument::preserveAspectRatio() const
{
return false;
}
inline int QSvgTinyDocument::currentElapsed() const
{
return m_time.elapsed();
}
inline int QSvgTinyDocument::animationDuration() const
{
return m_animationDuration;
}
QT_END_NAMESPACE
#endif // QSVGTINYDOCUMENT_P_H

176
svg/qsvgwidget.cpp Normal file
View File

@ -0,0 +1,176 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsvgwidget.h"
#ifndef QT_NO_WIDGETS
#include "qsvgrenderer.h"
#include "qstyleoption.h"
#include "qpainter.h"
#include "private/qwidget_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QSvgWidget
\inmodule QtSvg
\ingroup painting
\brief The QSvgWidget class provides a widget that is used to display the contents of
Scalable Vector Graphics (SVG) files.
\since 4.1
This class enables developers to display SVG drawings alongside standard widgets, and
is used in much the same way as QLabel is used for displaying text and bitmap images.
Since QSvgWidget is a subclass of QWidget, SVG drawings are rendered using the properties
of the display. More control can be exercised over the rendering process with the
QSvgRenderer class, as this can be used to paint onto other paint devices, such as QImage
and QGLWidget. The renderer used by the widget can be obtained with the renderer()
function.
Each QSvgWidget can be constructed with the file name of a SVG file, or they can be
constructed without a specific file to render and one can be supplied later. The load()
functions provide two different ways to load an SVG file: they accept either the file name
of an SVG file or a QByteArray containing the serialized XML representation of an SVG file.
By default, the widget provides a size hint to reflect the size of the drawing that it
displays. If no data has been loaded, the widget provides the default QWidget size hint.
Subclass this class and reimplement sizeHint() if you need to customize this behavior.
\sa QSvgRenderer, {Qt SVG C++ Classes}, QPicture
*/
class QSvgWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QSvgWidget)
public:
QSvgRenderer *renderer;
};
/*!
Constructs a new SVG display widget with the given \a parent.
*/
QSvgWidget::QSvgWidget(QWidget *parent)
: QWidget(*new QSvgWidgetPrivate, parent, 0)
{
d_func()->renderer = new QSvgRenderer(this);
QObject::connect(d_func()->renderer, SIGNAL(repaintNeeded()),
this, SLOT(update()));
}
/*!
Constructs a new SVG display widget with the given \a parent and loads the contents
of the specified \a file.
*/
QSvgWidget::QSvgWidget(const QString &file, QWidget *parent)
: QWidget(*new QSvgWidgetPrivate, parent, 0)
{
d_func()->renderer = new QSvgRenderer(file, this);
QObject::connect(d_func()->renderer, SIGNAL(repaintNeeded()),
this, SLOT(update()));
}
/*!
Destroys the widget.
*/
QSvgWidget::~QSvgWidget()
{
}
/*!
Returns the renderer used to display the contents of the widget.
*/
QSvgRenderer * QSvgWidget::renderer() const
{
Q_D(const QSvgWidget);
return d->renderer;
}
/*!
\reimp
*/
QSize QSvgWidget::sizeHint() const
{
Q_D(const QSvgWidget);
if (d->renderer->isValid())
return d->renderer->defaultSize();
else
return QSize(128, 64);
}
/*!
\reimp
*/
void QSvgWidget::paintEvent(QPaintEvent *)
{
Q_D(QSvgWidget);
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
d->renderer->render(&p);
}
/*!
Loads the contents of the specified SVG \a file and updates the widget.
*/
void QSvgWidget::load(const QString &file)
{
Q_D(const QSvgWidget);
d->renderer->load(file);
}
/*!
Loads the specified SVG format \a contents and updates the widget.
*/
void QSvgWidget::load(const QByteArray &contents)
{
Q_D(const QSvgWidget);
d->renderer->load(contents);
}
QT_END_NAMESPACE
#endif // QT_NO_WIDGETS

83
svg/qsvgwidget.h Normal file
View File

@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSVGWIDGET_H
#define QSVGWIDGET_H
#include <QtCore/qglobal.h>
#ifndef QT_NO_WIDGETS
#include <QtWidgets/qwidget.h>
#include <QtSvg/qtsvgglobal.h>
QT_BEGIN_NAMESPACE
class QSvgWidgetPrivate;
class QPaintEvent;
class QSvgRenderer;
class Q_SVG_EXPORT QSvgWidget : public QWidget
{
Q_OBJECT
public:
QSvgWidget(QWidget *parent = nullptr);
QSvgWidget(const QString &file, QWidget *parent = nullptr);
~QSvgWidget();
QSvgRenderer *renderer() const;
QSize sizeHint() const override;
public Q_SLOTS:
void load(const QString &file);
void load(const QByteArray &contents);
protected:
void paintEvent(QPaintEvent *event) override;
private:
Q_DISABLE_COPY(QSvgWidget)
Q_DECLARE_PRIVATE(QSvgWidget)
};
QT_END_NAMESPACE
#endif // QT_NO_WIDGETS
#endif // QSVGWIDGET_H

12
svg/qt_attribution.json Normal file
View File

@ -0,0 +1,12 @@
{
"Id": "xsvg",
"Name": "XSVG",
"QDocModule": "qtsvg",
"QtUsage": "Used in the Qt SVG library.",
"Files": "qtsvghandler.cpp",
"Description": "Some code for arc handling is derived from code from the XSVG project.",
"License": "MIT \"Old Style\" License",
"LicenseFile": "XSVG_LICENSE.txt",
"Copyright": "Copyright 2002 USC/Information Sciences Institute"
}

61
svg/qtsvgglobal.h Normal file
View File

@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTSVGGLOBAL_H
#define QTSVGGLOBAL_H
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
#ifndef Q_SVG_EXPORT
# ifndef QT_STATIC
# if defined(QT_BUILD_SVG_LIB)
# define Q_SVG_EXPORT Q_DECL_EXPORT
# else
# define Q_SVG_EXPORT Q_DECL_IMPORT
# endif
# else
# define Q_SVG_EXPORT
# endif
#endif
QT_END_NAMESPACE
#endif

58
svg/qtsvgglobal_p.h Normal file
View File

@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt SVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTSVGGLOBAL_P_H
#define QTSVGGLOBAL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtsvgglobal.h"
#define Q_SVG_PRIVATE_EXPORT Q_SVG_EXPORT
#endif // QTSVGGLOBAL_P_H

52
svg/svg.pro Normal file
View File

@ -0,0 +1,52 @@
TARGET = QtSvg
QT = core-private gui-private
qtHaveModule(widgets): QT += widgets-private
DEFINES += QT_NO_USING_NAMESPACE
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_DOCS = $$PWD/doc/qtsvg.qdocconf
HEADERS += \
qsvggraphics_p.h \
qsvghandler_p.h \
qsvgnode_p.h \
qsvgstructure_p.h \
qsvgstyle_p.h \
qsvgfont_p.h \
qsvgtinydocument_p.h \
qsvgrenderer.h \
qsvgwidget.h \
qgraphicssvgitem.h \
qsvggenerator.h \
qtsvgglobal.h
SOURCES += \
qsvggraphics.cpp \
qsvghandler.cpp \
qsvgnode.cpp \
qsvgstructure.cpp \
qsvgstyle.cpp \
qsvgfont.cpp \
qsvgtinydocument.cpp \
qsvgrenderer.cpp \
qsvgwidget.cpp \
qgraphicssvgitem.cpp \
qsvggenerator.cpp
qtConfig(system-zlib): \
QMAKE_USE_PRIVATE += zlib
else: \
QT_PRIVATE += zlib-private
load(qt_module)
CONFIG(debug, debug|release){
DESTDIR = ../Bin
TARGET = $$join(TARGET,,,) #为debug版本生成的文件增加d的后缀
} else {
DESTDIR = ../Bin
TARGET = $$join(TARGET,,,)
}

337
svg/svg.pro.user Normal file
View File

@ -0,0 +1,337 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.9.1, 2025-12-10T14:25:22. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{04219d0a-2df9-4f31-921d-c25f7a4fa4e5}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">0</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
<value type="QString">-fno-delayed-template-parsing</value>
</valuelist>
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.13.0 MSVC2017 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.13.0 MSVC2017 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5130.win64_msvc2017_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Qt/Qt5.13.0/5.13.0/Src/qtsvg/src/build-svg-Desktop_Qt_5_13_0_MSVC2017_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Qt/Qt5.13.0/5.13.0/Src/qtsvg/src/build-svg-Desktop_Qt_5_13_0_MSVC2017_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Qt/Qt5.13.0/5.13.0/Src/qtsvg/src/build-svg-Desktop_Qt_5_13_0_MSVC2017_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Custom Executable</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">21</value>
</data>
<data>
<variable>Version</variable>
<value type="int">21</value>
</data>
</qtcreator>