引入了第三方库

dev-VirtualTexture
白封羽 2023-01-12 15:04:44 +08:00
parent fe6e10c882
commit dc89e02515
11 changed files with 1703 additions and 84 deletions

View File

@ -32,7 +32,7 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
<QtInstall>5.15.2_msvc2019_64</QtInstall> <QtInstall>5.15.2_msvc2019_64</QtInstall>
<QtModules>core;gui;widgets;winextras</QtModules> <QtModules>core;xml;gui;svg;widgets;winextras</QtModules>
<QtBuildConfig>debug</QtBuildConfig> <QtBuildConfig>debug</QtBuildConfig>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
@ -105,6 +105,7 @@
<ClCompile Include="src\Editor\LayerManager.cpp" /> <ClCompile Include="src\Editor\LayerManager.cpp" />
<ClCompile Include="src\Editor\LayerWrapper.cpp" /> <ClCompile Include="src\Editor\LayerWrapper.cpp" />
<ClCompile Include="src\Editor\PreviewWindow.cpp" /> <ClCompile Include="src\Editor\PreviewWindow.cpp" />
<ClCompile Include="src\Editor\third-party modules\qquick\qquicksvgparser.cpp" />
<ClCompile Include="src\IconWidget.cpp" /> <ClCompile Include="src\IconWidget.cpp" />
<ClCompile Include="src\main.cpp" /> <ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainWindow.cpp" /> <ClCompile Include="src\MainWindow.cpp" />
@ -129,6 +130,7 @@
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" /> <ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
<ClCompile Include="src\SvgParser.cpp" /> <ClCompile Include="src\SvgParser.cpp" />
<ClCompile Include="src\TitleWidget.cpp" /> <ClCompile Include="src\TitleWidget.cpp" />
<ClCompile Include="src\Editor\third-party modules\SvgHelper.cpp" />
<QtRcc Include="MainWindow.qrc" /> <QtRcc Include="MainWindow.qrc" />
<QtUic Include="EditorWidget.ui" /> <QtUic Include="EditorWidget.ui" />
<QtUic Include="FramelessWindow.ui" /> <QtUic Include="FramelessWindow.ui" />
@ -158,6 +160,10 @@
<None Include="Shaders\ssgi.comp" /> <None Include="Shaders\ssgi.comp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal.h" />
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal_p.h" />
<ClInclude Include="src\Editor\third-party modules\qquick\qquicksvgparser_p.h" />
<ClInclude Include="src\Editor\third-party modules\SvgHelper.h" />
<QtMoc Include="src\MainWindow.h" /> <QtMoc Include="src\MainWindow.h" />
<ClInclude Include="src\Editor\ElementManager.h" /> <ClInclude Include="src\Editor\ElementManager.h" />
<ClInclude Include="src\Editor\GraphicElement.h" /> <ClInclude Include="src\Editor\GraphicElement.h" />

View File

@ -147,6 +147,12 @@
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp"> <ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp">
<Filter>Source Files\Renderer\Painting</Filter> <Filter>Source Files\Renderer\Painting</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Editor\third-party modules\SvgHelper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Editor\third-party modules\qquick\qquicksvgparser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h"> <QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -312,6 +318,18 @@
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h"> <ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h">
<Filter>Header Files\Renderer\Painting</Filter> <Filter>Header Files\Renderer\Painting</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Editor\third-party modules\SvgHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Editor\third-party modules\qquick\qquicksvgparser_p.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal_p.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtRcc Include="MainWindow.qrc"> <QtRcc Include="MainWindow.qrc">

View File

@ -1,75 +1,19 @@
#include "GraphicElement.h" #include "GraphicElement.h"
using namespace std; using namespace std;
string ElementTypeStringValue::sStringTag[] = {"undefined", "path", "polygon", "round"};
string ElementTypeStringValue::stringType(ElementType elementType)
{
int type = static_cast<int>(elementType);
return sStringTag[type];
}
ElementType ElementTypeStringValue::enumType(std::string elementType)
{
for (int i = 1; i <= sElementType; i++)
{
if (elementType == sStringTag[i])
{
return static_cast<ElementType>(i);
}
}
return ElementType::undefined;
}
QPainterPath SimpleElement::getPaintObject() const QPainterPath SimpleElement::getPaintObject() const
{ {
return painterPath; return painterPath;
} }
void SimpleElement::loadSvgFile(const QString& filePath)
{
// TODO // TODO
void SimpleElement::pathOperate(QJsonArray paths)
{
QRect r(100, 100, 100, 100);
painterPath.addRect(r);
}
void SimpleElement::polygonOperate(QJsonArray points)
{
QPolygonF polygon;
for (auto &&point : points)
{
polygon.append(QPointF(point.toObject().value("x").toDouble(), point.toObject().value("y").toDouble()));
}
painterPath.addPolygon(polygon);
}
void SimpleElement::roundOperate(QJsonObject json)
{
double xAxis = json.value("x-axis").toDouble();
double yAxis = json.value("y-axis").toDouble();
double origin = json.value("origin").toDouble();
double angle = json.value("angle").toDouble();
painterPath.arcMoveTo(xAxis * -0.5, yAxis * -0.5, xAxis, yAxis, origin);
painterPath.arcTo(xAxis * -0.5, yAxis * -0.5, xAxis, yAxis, origin, angle);
} }
SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource) SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource)
{ {
painterPath.clear(); painterPath.clear();
elementType = ElementTypeStringValue::enumType(jsonSource.value("type").toString().toStdString()); loadSvgFile(jsonSource.value("data").toObject().value("include").toString());
switch (elementType)
{
case ElementType::undefined:
break;
case ElementType::path: {
QJsonArray paths = jsonSource.value("data").toObject().value("operations").toArray();
pathOperate(paths);
break;
}
case ElementType::polygon: {
QJsonArray points = jsonSource.value("data").toObject().value("points").toArray();
polygonOperate(points);
break;
}
case ElementType::round: {
roundOperate(jsonSource.value("data").toObject());
break;
}
default:
break;
}
} }
GroupElement::GroupElement(FolderLayerWrapper *sourceLayer) GroupElement::GroupElement(FolderLayerWrapper *sourceLayer)

View File

@ -8,26 +8,10 @@ class LayerWrapper;
class LeafLayerWrapper; class LeafLayerWrapper;
class FolderLayerWrapper; class FolderLayerWrapper;
enum class ElementType
{
undefined = 0,
path = 1,
polygon = 2,
round = 3
};
class ElementTypeStringValue
{
private:
static std::string sStringTag[];
static const int sElementType = 3;
public:
static std::string stringType(ElementType elementType);
static ElementType enumType(std::string elementType);
};
class GraphicElement class GraphicElement
{ {
public: public:
QString name="";
virtual QPainterPath getPaintObject() const = 0; virtual QPainterPath getPaintObject() const = 0;
}; };
class SimpleElement : public GraphicElement class SimpleElement : public GraphicElement
@ -35,10 +19,7 @@ class SimpleElement : public GraphicElement
private: private:
QJsonObject jsonSource; QJsonObject jsonSource;
QPainterPath painterPath; QPainterPath painterPath;
ElementType elementType; void loadSvgFile(const QString& filePath);
void pathOperate(QJsonArray paths);
void polygonOperate(QJsonArray points);
void roundOperate(QJsonObject json);
public: public:
SimpleElement(QJsonObject jsonSource); SimpleElement(QJsonObject jsonSource);

View File

@ -35,7 +35,7 @@ void PreviewWindow::initializeGL()
initializeOpenGLFunctions(); initializeOpenGLFunctions();
glClearColor(1.0, 1.0, 1.0, 1.0); glClearColor(1.0, 1.0, 1.0, 1.0);
} }
#include "./third-party modules/qquick/qquicksvgparser_p.h"
void PreviewWindow::paintGL() void PreviewWindow::paintGL()
{ {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);

View File

@ -0,0 +1,857 @@
#include "SvgHelper.h"
//方便调试时的打印输出
#define qout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]\t"
SvgHelper::SvgHelper()
{
}
void SvgHelper::parseSvgImage(QString filepath)
{
this->filepath = filepath;
QFile svgFile(filepath);
if (svgFile.open(QFile::ReadOnly)) {
QDomDocument doc;
if (doc.setContent(&svgFile))
{
svgFile.close();
// 返回根节点
QDomElement root = doc.documentElement();
qout << "root:" << root.nodeName();
// 获得第一个子节点
QDomNode node = root.firstChild();
while (!node.isNull()) //如果节点不空
{
if (node.isElement()) //如果节点是元素
{
//转换为元素
QDomElement e = node.toElement();
QString tagname = e.tagName();
qout << "tagname:" << tagname;
if (typeList.contains(tagname)) {
parseSVGTag(e, tagname);
}
else {
foreach(QString type, typeList) {
QDomNodeList list = e.elementsByTagName(type);
if (list.length() > 0) {
for (int i = 0; i < list.count(); i++) {
QDomNode n = list.at(i);
parseSVGTag(n.toElement(), n.nodeName());
}
}
}
}
}
// 下一个兄弟节点
node = node.nextSibling();
}
}
}
}
QSize matchSize(QString path)
{
QSvgWidget svgWidget(path);
QSvgRenderer* render = svgWidget.renderer();
QSize size = render->defaultSize();
QRect rect = render->viewBox();
if (rect.size() != size) {
size = rect.size();
}
return size;
}
QImage SvgHelper::getSvgImage() {
auto imagesize = matchSize(filepath);
QImage image(imagesize, QImage::Format_ARGB32);
image.fill(QColor(255, 255, 255, 255));
QPainter p;
p.begin(&image);
p.setPen(Qt::black);
foreach(QPainterPath ppath, svgPathList) {
p.drawPath(ppath);
}
p.end();
return image;
}
void SvgHelper::parseSVGTag(QDomElement e, QString tagname)
{
if (QString::compare(tagname, "path", Qt::CaseInsensitive) == 0) { // 路径
QString pathvalue = e.attribute("d");
qout << pathvalue;
parseSvgPath(pathvalue, paintPath);
}
else if (QString::compare(tagname, "rect", Qt::CaseInsensitive) == 0) {
float x = getValueWithoutUnit(e.attribute("x"));
float y = getValueWithoutUnit(e.attribute("y"));
float width = getValueWithoutUnit(e.attribute("width"));
float height = getValueWithoutUnit(e.attribute("height"));
float rx = getValueWithoutUnit(e.attribute("rx"));
float ry = getValueWithoutUnit(e.attribute("rx"));
qout << x << y << width << height << rx << ry;
if (rx < 0 || ry < 0) {
paintPath.moveTo(x, y);
paintPath.lineTo(x + width, y);
paintPath.lineTo(x + width, y + height);
paintPath.lineTo(x, y + height);
paintPath.lineTo(x, y);
paintPath.moveTo(x, y);
{
QList<QPointF> list;
list.append(QPointF(x, y));
list.append(QPointF(x + width, y));
list.append(QPointF(x + width, y + height));
list.append(QPointF(x, y));
svgPointList.append(list);
}
}
else {
float r = qMax(rx, ry);
paintPath.moveTo(x + r, y);
paintPath.lineTo(x + width - r, y);
QRectF rect(x + width - 2 * r, y, 2 * r, 2 * r);
paintPath.arcTo(rect, 90, -90);
paintPath.lineTo(x + width, y + height - r);
rect = QRectF(x + width - 2 * r, y + height - 2 * r, 2 * r, 2 * r);
paintPath.arcTo(rect, 0, -90);
paintPath.lineTo(x + r, y + height);
rect = QRectF(x, y + height - 2 * r, 2 * r, 2 * r);
paintPath.arcTo(rect, -90, -90);
paintPath.lineTo(x, y + r);
rect = QRectF(x, y, 2 * r, 2 * r);
paintPath.arcTo(rect, 180, -90);
paintPath.moveTo(x + r, y);
{
QPainterPath path;
QList<QPointF> list;
list.append(QPointF(x + r, y));
list.append(QPointF(x + width - r, y));
QRectF rect(x + width - 2 * r, y, 2 * r, 2 * r);
path.moveTo(x + width - r, y);
path.arcTo(rect, 90, -90);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
list.append(QPointF(x + width, y + height - r));
path.clear();
rect = QRectF(x + width - 2 * r, y + height - 2 * r, 2 * r, 2 * r);
path.arcTo(rect, 0, -90);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
list.append(QPointF(x + r, y + height));
path.clear();
rect = QRectF(x, y + height - 2 * r, 2 * r, 2 * r);
path.arcTo(rect, -90, -90);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
list.append(QPointF(x, y + r));
path.clear();
rect = QRectF(x, y, 2 * r, 2 * r);
path.arcTo(rect, 180, -90);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
list.append(QPointF(x + r, y));
svgPointList.append(list);
}
}
}
else if (QString::compare(tagname, "circle", Qt::CaseInsensitive) == 0) {
float cx = getValueWithoutUnit(e.attribute("cx"));
float cy = getValueWithoutUnit(e.attribute("cy"));
float r = getValueWithoutUnit(e.attribute("r"));
cx = cx < 0 ? 0 : cx;
cy = cy < 0 ? 0 : cy;
qout << cx << cy << r;
if (r > 0) {
paintPath.moveTo(cx + r, cy);
paintPath.arcTo(cx - r, cy - r, 2 * r, 2 * r, 0, 360);
paintPath.moveTo(cx + r, cy);
{
QPainterPath path;
QList<QPointF> list;
path.moveTo(cx + r, cy);
path.arcTo(cx - r, cy - r, 2 * r, 2 * r, 0, 360);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
svgPointList.append(list);
}
}
}
else if (QString::compare(tagname, "ellipse", Qt::CaseInsensitive) == 0) {
float cx = getValueWithoutUnit(e.attribute("cx"));
float cy = getValueWithoutUnit(e.attribute("cy"));
float rx = getValueWithoutUnit(e.attribute("rx"));
float ry = getValueWithoutUnit(e.attribute("ry"));
cx = cx < 0 ? 0 : cx;
cy = cy < 0 ? 0 : cy;
qout << cx << cy << rx << ry;
if (rx > 0 && ry > 0) {
paintPath.moveTo(cx + rx, cy);
paintPath.arcTo(cx - rx, cy - ry, 2 * rx, 2 * ry, 0, 360);
paintPath.moveTo(cx + rx, cy);
{
QPainterPath path;
QList<QPointF> list;
path.moveTo(cx + rx, cy);
path.arcTo(cx - rx, cy - ry, 2 * rx, 2 * ry, 0, 360);
for (double i = 0; i < 1; i += 1.0 / path.length()) list.append(path.pointAtPercent(i));
list.append(path.pointAtPercent(1));
svgPointList.append(list);
}
}
}
else if (QString::compare(tagname, "line", Qt::CaseInsensitive) == 0) {
float x1 = getValueWithoutUnit(e.attribute("x1"));
float y1 = getValueWithoutUnit(e.attribute("y1"));
float x2 = getValueWithoutUnit(e.attribute("x2"));
float y2 = getValueWithoutUnit(e.attribute("y2"));
qout << x1 << y1 << x2 << y2;
paintPath.moveTo(x1, y1);
paintPath.lineTo(x2, y2);
paintPath.moveTo(x2, y2);
{
QList<QPointF> list;
list.append(QPointF(x1, y1));
list.append(QPointF(x2, y2));
svgPointList.append(list);
}
}
else if (QString::compare(tagname, "polygon", Qt::CaseInsensitive) == 0) {
QString value = e.attribute("points");
qout << value;
QVector<float> vPos = segmentationCoordinates(value);
qout << vPos;
QPointF startPoint;
QList<QPointF> list;
if (vPos.length() > 1) {
startPoint = QPointF(vPos[0], vPos[1]);
paintPath.moveTo(startPoint);
list.append(startPoint);
vPos.removeFirst(); vPos.removeFirst();
}
while (vPos.length() / 2 >= 1) {
paintPath.lineTo(vPos[0], vPos[1]);
list.append(QPointF(vPos[0], vPos[1]));
vPos.removeFirst(); vPos.removeFirst();
}
if (!startPoint.isNull()) {
paintPath.lineTo(startPoint);
paintPath.moveTo(startPoint);
list.append(startPoint);
}
if (!list.isEmpty()) svgPointList.append(list);
}
else if (QString::compare(tagname, "polyline", Qt::CaseInsensitive) == 0) {
QString value = e.attribute("points");
qout << value;
QVector<float> vPos = segmentationCoordinates(value);
qout << vPos;
QPointF startPoint;
QList<QPointF> list;
if (vPos.length() > 1) {
startPoint = QPointF(vPos[0], vPos[1]);
paintPath.moveTo(startPoint);
list.append(startPoint);
vPos.removeFirst(); vPos.removeFirst();
}
while (vPos.length() / 2 >= 1) {
paintPath.lineTo(vPos[0], vPos[1]);
list.append(QPointF(vPos[0], vPos[1]));
vPos.removeFirst(); vPos.removeFirst();
}
if (!startPoint.isNull()) {
paintPath.moveTo(startPoint);
// list.append(startPoint);
}
if (!list.isEmpty()) svgPointList.append(list);
}
if (!paintPath.isEmpty()) {
svgPathList.append(paintPath);
}
paintPath.clear();
if (!testpathlist.isEmpty()) {
svgPointList.append(testpathlist);
}
testpathlist.clear();
}
void SvgHelper::parseSvgPath(QString path, QPainterPath& paintPath)
{
QString cmdLine = "";
foreach(QChar c, path) {
if (cmdList.contains(c)) {
qout << cmdLine;
if (!cmdLine.isEmpty()) {
dealParsePainter(paintPath, cmdLine);
cmdLine.clear();
}
}
cmdLine += c;
}
if (!cmdLine.isEmpty()) {
dealParsePainter(paintPath, cmdLine);
cmdLine.clear();
}
}
void SvgHelper::dealParsePainter(QPainterPath& path, QString line)
{
line = line.trimmed();
int coordinates;
QString cmd = line.mid(0, 1);
QString value = line.mid(1);
if (cmd.isUpper()) coordinates = ABSOLUTE_COORDINATES;
else coordinates = RELATIVE_COORDINATES;
QVector<float> vNum = segmentationCoordinates(value);
qout << vNum;
switch (cmdTypeList.indexOf(cmd.toUpper().at(0))) {
case 0: // m
{
bool hasLineflag = vNum.length() > 2;
bool lineto = false;
if (!path.isEmpty()) svgPathList.append(path);
path.clear();
if (!testpathlist.isEmpty()) svgPointList.append(testpathlist);
testpathlist.clear();
while (vNum.length() / 2 >= 1) {
QPointF point(vNum.at(0), vNum.at(1));
if (coordinates == ABSOLUTE_COORDINATES) {
nowPositon = point;
if (lineto) path.lineTo(nowPositon);
else path.moveTo(nowPositon);
testpathlist.append(nowPositon);
}
else {
nowPositon = nowPositon + point;
if (lineto) path.lineTo(nowPositon);
else path.moveTo(nowPositon);
testpathlist.append(nowPositon);
}
qout << "当前坐标" << nowPositon;
if (!lineto) pathStartPosition = nowPositon;
for (int i = 0; i < 2; i++) vNum.removeFirst();
if (hasLineflag) lineto = true;
}
break;
}
case 1: // l
{
while (vNum.length() / 2 >= 1) {
QPointF point(vNum.at(0), vNum.at(1));
if (coordinates == ABSOLUTE_COORDINATES) {
path.lineTo(point);
testpathlist.append(point);
nowPositon = point;
}
else {
QPointF targetPoint = nowPositon + point;
path.lineTo(targetPoint);
testpathlist.append(targetPoint);
nowPositon = targetPoint;
}
qout << "当前坐标" << nowPositon;
path.moveTo(nowPositon);
for (int i = 0; i < 2; i++) vNum.removeFirst();
}
break;
}
case 2: // h
{
while (vNum.length() >= 1) {
if (coordinates == ABSOLUTE_COORDINATES) {
QPointF point(vNum.at(0), nowPositon.y());
path.lineTo(point);
testpathlist.append(point);
nowPositon = point;
}
else {
QPointF point(nowPositon.x() + vNum.at(0), nowPositon.y());
path.lineTo(point);
testpathlist.append(point);
nowPositon = point;
}
qout << "当前坐标" << nowPositon;
path.moveTo(nowPositon);
vNum.removeFirst();
}
break;
}
case 3: // v
{
while (vNum.length() >= 1) {
if (coordinates == ABSOLUTE_COORDINATES) {
QPointF point(nowPositon.x(), vNum.at(0));
path.lineTo(point);
testpathlist.append(point);
nowPositon = point;
}
else {
QPointF point(nowPositon.x(), nowPositon.y() + vNum.at(0));
path.lineTo(point);
testpathlist.append(point);
nowPositon = point;
}
qout << "当前坐标" << nowPositon;
path.moveTo(nowPositon);
vNum.removeFirst();
}
break;
}
case 4: // c
{
while (vNum.length() / 6 >= 1) {
QPointF startPoint = nowPositon;
QPointF c1, c2, endPoint;
if (coordinates == ABSOLUTE_COORDINATES) {
c1 = QPointF(vNum.at(0), vNum.at(1));
c2 = QPointF(vNum.at(2), vNum.at(3));
endPoint = QPointF(vNum.at(4), vNum.at(5));
}
else {
float x = startPoint.x();
float y = startPoint.y();
c1 = QPointF(x + vNum.at(0), y + vNum.at(1));
c2 = QPointF(x + vNum.at(2), y + vNum.at(3));
endPoint = QPointF(x + vNum.at(4), y + vNum.at(5));
}
lastControlPosition = c2;
path.moveTo(startPoint);
path.cubicTo(c1, c2, endPoint); // 三次贝塞尔曲线
path.moveTo(endPoint);
{
QPainterPath testpath;
testpath.moveTo(startPoint);
testpath.cubicTo(c1, c2, endPoint); // 三次贝塞尔曲线
testpath.moveTo(endPoint);
for (double i = 0; i <= 1; i += 1.0 / testpath.length()) testpathlist.append(testpath.pointAtPercent(i));
}
nowPositon = endPoint;
qout << "当前坐标" << nowPositon;
for (int i = 0; i < 6; i++) vNum.removeFirst();
}
break;
}
case 5: // s
{
while (vNum.length() / 4 >= 1) {
QPointF startPoint = nowPositon;
QPointF c1, c2, endPoint;
if (coordinates == ABSOLUTE_COORDINATES) {
float x = startPoint.x();
float y = startPoint.y();
c1 = QPointF(2 * x - lastControlPosition.x(), 2 * y - lastControlPosition.y());
c2 = QPointF(vNum.at(0), vNum.at(1));
endPoint = QPointF(vNum.at(2), vNum.at(3));
}
else {
float x = startPoint.x();
float y = startPoint.y();
c1 = QPointF(x + x - lastControlPosition.x(), y + y - lastControlPosition.y());
c2 = QPointF(x + vNum.at(0), y + vNum.at(1));
endPoint = QPointF(x + vNum.at(2), y + vNum.at(3));
}
lastControlPosition = c2;
path.moveTo(startPoint);
path.cubicTo(c1, c2, endPoint); // 三次贝塞尔曲线
path.moveTo(endPoint);
{
QPainterPath testpath;
testpath.moveTo(startPoint);
testpath.cubicTo(c1, c2, endPoint); // 三次贝塞尔曲线
testpath.moveTo(endPoint);
for (double i = 0; i <= 1; i += 1.0 / testpath.length()) testpathlist.append(testpath.pointAtPercent(i));
}
nowPositon = endPoint;
qout << "当前坐标" << nowPositon;
for (int i = 0; i < 4; i++) vNum.removeFirst();
}
break;
}
case 6: // q
{
while (vNum.length() / 4 >= 1) {
QPointF startPoint = nowPositon;
QPointF cPoint;
QPointF endPoint;
if (coordinates == ABSOLUTE_COORDINATES) {
cPoint = QPointF(vNum.at(0), vNum.at(1));
endPoint = QPointF(vNum.at(2), vNum.at(3));
}
else {
float x = startPoint.x();
float y = startPoint.y();
cPoint = QPointF(x + vNum.at(0), y + vNum.at(1));
endPoint = QPointF(x + vNum.at(2), y + vNum.at(3));
}
lastControlPosition = cPoint;
path.moveTo(startPoint);
path.quadTo(cPoint, endPoint); // 二次贝塞尔曲线
path.moveTo(endPoint);
{
QPainterPath testpath;
testpath.moveTo(startPoint);
testpath.quadTo(cPoint, endPoint); // 二次贝塞尔曲线
testpath.moveTo(endPoint);
for (double i = 0; i <= 1; i += 1.0 / testpath.length()) testpathlist.append(testpath.pointAtPercent(i));
}
nowPositon = endPoint;
qout << "当前坐标" << nowPositon;
for (int i = 0; i < 4; i++) vNum.removeFirst();
}
break;
}
case 7: // t
{
while (vNum.length() / 2 >= 1) {
QPointF startPoint = nowPositon;
QPointF cPoint;
QPointF endPoint;
if (coordinates == ABSOLUTE_COORDINATES) {
float x = startPoint.x();
float y = startPoint.y();
cPoint = QPointF(2 * x - lastControlPosition.x(), 2 * y - lastControlPosition.y());
endPoint = QPointF(vNum.at(0), vNum.at(1));
}
else {
float x = startPoint.x();
float y = startPoint.y();
cPoint = QPointF(x + x - lastControlPosition.x(), y + y - lastControlPosition.y());
endPoint = QPointF(x + vNum.at(0), y + vNum.at(1));
}
lastControlPosition = cPoint;
path.moveTo(startPoint);
path.quadTo(cPoint, endPoint); // 二次贝塞尔曲线
path.moveTo(endPoint);
{
QPainterPath testpath;
testpath.moveTo(startPoint);
testpath.quadTo(cPoint, endPoint); // 二次贝塞尔曲线
testpath.moveTo(endPoint);
for (double i = 0; i <= 1; i += 1.0 / testpath.length()) testpathlist.append(testpath.pointAtPercent(i));
}
nowPositon = endPoint;
qout << "当前坐标" << nowPositon;
for (int i = 0; i < 2; i++) vNum.removeFirst();
}
break;
}
case 8: // a
{
while (vNum.length() / 7 >= 1) {
QPointF startPoint = nowPositon;
float rx = vNum.at(0);
float ry = vNum.at(1);
float x_axis_rotation = vNum.at(2);
float large_arc_flag = vNum.at(3);
float sweep_flag = vNum.at(4);
QPointF endPoint;
double cx;
double cy;
double start_angle;
double delta_angle;
if (coordinates == ABSOLUTE_COORDINATES) {
endPoint = QPointF(vNum.at(5), vNum.at(6));
}
else {
float x = startPoint.x();
float y = startPoint.y();
endPoint = QPointF(x + vNum.at(5), y + vNum.at(6));
}
// svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
// x1 y1 rx ry φ fA fS x2 y2
svgArcToCenterParam(startPoint.x(), startPoint.y(), rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, endPoint.x(), endPoint.y(),
cx, cy, start_angle, delta_angle);
start_angle = qRadiansToDegrees(start_angle);
delta_angle = qRadiansToDegrees(delta_angle);
QRectF rect(cx - rx, cy - ry, 2 * rx, 2 * ry);
qout << "转换后" << cx << cy << start_angle << delta_angle << rect;
if (delta_angle != 0) {
path.moveTo(startPoint);
path.arcTo(rect, 360 - start_angle, -delta_angle); // 绘图的坐标系与笛卡尔坐标系不同, 需要转换
{
QPainterPath testpath;
testpath.moveTo(startPoint);
testpath.arcTo(rect, 360 - start_angle, -delta_angle);
testpath.moveTo(endPoint);
for (double i = 0; i <= 1; i += 1.0 / testpath.length()) testpathlist.append(testpath.pointAtPercent(i));
}
}
path.moveTo(endPoint);
nowPositon = endPoint;
qout << "当前坐标" << nowPositon;
for (int i = 0; i < 7; i++) vNum.removeFirst();
}
break;
}
case 9: // z
qout << "z:" << pathStartPosition;
path.lineTo(pathStartPosition);
testpathlist.append(pathStartPosition);
break;
}
}
QVector<float> SvgHelper::segmentationCoordinates(QString value)
{
// 将科学记数法暂时替换, 防止分割出错
if (value.contains("e", Qt::CaseInsensitive)) {
value.replace("e-", "[KXJSFF]");
value.replace("E-", "[KXJSFF]");
}
if (value.contains(" -")) {
value.replace(" -", " [KGFS]");
}
if (value.contains(",-")) {
value.replace(",-", ",[DHFS]");
}
qout << "------value:------" << value;
QVector<float> vPos;
QString num = "";
foreach(QChar c, value) {
if (splitList.contains(c)) {
num = num.trimmed();
if (!num.isEmpty()) {
if (num.contains(',')) num.remove(',');
vPos.append(getValueWithoutUnit(num));
num.clear();
}
}
num += c;
}
num = num.trimmed();
if (num.contains(',')) num.remove(',');
if (!num.isEmpty()) vPos.append(getValueWithoutUnit(num));
qout << "------num:------" << num;
return vPos;
}
float SvgHelper::getValueWithoutUnit(QString input)
{
// 将科学记数法替换回来
if (input.contains("[KXJSFF]")) input.replace("[KXJSFF]", "e-");
if (input.contains("[KGFS]")) input.replace("[KGFS]", "-");
if (input.contains("[DHFS]")) input.replace("[DHFS]", "-");
qout << "------input:------" << input;
if (input.isEmpty()) return -1;
QString str = input;
foreach(QString unit, unitList) {
if (str.contains(unit)) {
str.remove(unit);
}
}
return str.toFloat();
}
/**
svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x2 y2)+
(x1 y1)
(x2 y2)
rx X
ry Y
x-axis-rotation X
large-arc-flag
sweep-flag
sample : svgArcToCenterParam(200,200,50,50,0,1,1,300,200, output...)
*/
double SvgHelper::radian(double ux, double uy, double vx, double vy) {
double dot = ux * vx + uy * vy;
double mod = sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
double rad = acos(dot / mod);
if (ux * vy - uy * vx < 0.0) rad = -rad;
return rad;
}
int SvgHelper::svgArcToCenterParam(double x1, double y1, double rx, double ry, double phi, double fA, double fS, double x2, double y2,
double& cx_out, double& cy_out, double& startAngle_out, double& deltaAngle_out) {
double cx, cy, startAngle, deltaAngle, endAngle;
double PIx2 = M_PI * 2.0;
if (rx < 0) {
rx = -rx;
}
if (ry < 0) {
ry = -ry;
}
if (rx == 0.0 || ry == 0.0) { // invalid arguments
return -1;
}
double s_phi = sin(phi);
double c_phi = cos(phi);
double hd_x = (x1 - x2) / 2.0; // half diff of x
double hd_y = (y1 - y2) / 2.0; // half diff of y
double hs_x = (x1 + x2) / 2.0; // half sum of x
double hs_y = (y1 + y2) / 2.0; // half sum of y
// F6.5.1
double x1_ = c_phi * hd_x + s_phi * hd_y;
double y1_ = c_phi * hd_y - s_phi * hd_x;
// F.6.6 Correction of out-of-range radii
// Step 3: Ensure radii are large enough
double lambda = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
if (lambda > 1) {
rx = rx * sqrt(lambda);
ry = ry * sqrt(lambda);
}
double rxry = rx * ry;
double rxy1_ = rx * y1_;
double ryx1_ = ry * x1_;
double sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
if (!sum_of_sq) {
return -1;
}
double coe = sqrt(abs((rxry * rxry - sum_of_sq) / sum_of_sq));
if (fA == fS) { coe = -coe; }
// F6.5.2
double cx_ = coe * rxy1_ / ry;
double cy_ = -coe * ryx1_ / rx;
// F6.5.3
cx = c_phi * cx_ - s_phi * cy_ + hs_x;
cy = s_phi * cx_ + c_phi * cy_ + hs_y;
double xcr1 = (x1_ - cx_) / rx;
double xcr2 = (x1_ + cx_) / rx;
double ycr1 = (y1_ - cy_) / ry;
double ycr2 = (y1_ + cy_) / ry;
// F6.5.5
startAngle = radian(1.0, 0.0, xcr1, ycr1);
// F6.5.6
deltaAngle = radian(xcr1, ycr1, -xcr2, -ycr2);
while (deltaAngle > PIx2) { deltaAngle -= PIx2; }
while (deltaAngle < 0.0) { deltaAngle += PIx2; }
if (fS == false || fS == 0) { deltaAngle -= PIx2; }
endAngle = startAngle + deltaAngle;
while (endAngle > PIx2) { endAngle -= PIx2; }
while (endAngle < 0.0) { endAngle += PIx2; }
cx_out = cx;
cy_out = cy;
startAngle_out = startAngle;
deltaAngle_out = deltaAngle;
return 1;
}
QList<QList<QPointF> > SvgHelper::getSvgPointList() const
{
return svgPointList;
}
QList<QPainterPath> SvgHelper::getSvgPathList() const
{
return svgPathList;
}
/*
get angle ACB, point C is the center point
A(x1,y1)
B(x2,y2)
C(x3,y3)
*/
double SvgHelper::get_angle_with_points(double x1, double y1, double x2, double y2, double x3, double y3)
{
double theta = atan2(x1 - x3, y1 - y3) - atan2(x2 - x3, y2 - y3);
if (theta > M_PI)
theta -= 2 * M_PI;
if (theta < -M_PI)
theta += 2 * M_PI;
theta = abs(theta * 180.0 / M_PI);
if (y2 <= y3) {
theta = 360.0 - theta;
}
return theta;
}

View File

@ -0,0 +1,60 @@
#pragma once
#ifndef SVGHELPER_H
#define SVGHELPER_H
#include <QDebug>
#include <QDomDocument>
#include <QPainter>
#include <QPainterPath>
#include <QSvgRenderer>
#include <QSvgWidget>
#include <QVector>
#include <QXmlStreamReader>
#include <QtXml>
#include <vector>
using namespace std;
const QList<QChar> cmdList = {'M', 'm', 'L', 'l', 'H', 'h', 'V', 'v', 'C', 'c',
'S', 's', 'Q', 'q', 'T', 't', 'A', 'a', 'Z', 'z'};
const QList<QChar> cmdTypeList = {'M', 'L', 'H', 'V', 'C', 'S', 'Q', 'T', 'A', 'Z'};
const QList<QChar> splitList = {' ', '-', ',', '\r', '\n', '\t'};
const QList<QString> unitList = {"em", "px", "%", "cm", "mm", "in", "pt", "pc"};
const QList<QString> typeList = {"path", "rect", "circle", "ellipse", "line", "polygon", "polyline"};
#define ABSOLUTE_COORDINATES 1
#define RELATIVE_COORDINATES 2
class SvgHelper
{
public:
SvgHelper();
void parseSvgImage(QString filepath);
QList<QPainterPath> getSvgPathList() const;
QImage getSvgImage();
QList<QList<QPointF>> getSvgPointList() const;
private:
void parseSVGTag(QDomElement e, QString tagname);
void parseSvgPath(QString path, QPainterPath &paintPath);
void dealParsePainter(QPainterPath &path, QString line);
QVector<float> segmentationCoordinates(QString value);
float getValueWithoutUnit(QString input);
double radian(double ux, double uy, double vx, double vy);
int svgArcToCenterParam(double x1, double y1, double rx, double ry, double phi, double fA, double fS, double x2,
double y2, double &cx_out, double &cy_out, double &startAngle_out, double &deltaAngle_out);
double get_angle_with_points(double x1, double y1, double x2, double y2, double x3, double y3);
QString filepath;
QPainterPath paintPath;
QList<QPointF> testpathlist;
QPointF nowPositon = QPointF(0, 0);
QPointF pathStartPosition = QPointF(0, 0);
QPointF lastControlPosition = QPointF(0, 0);
QList<QPainterPath> svgPathList;
QList<QList<QPointF>> svgPointList;
};
#endif // SVGHELPER_H

View File

@ -0,0 +1,567 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Quick 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 "qquicksvgparser_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
//copied from Qt SVG (qsvghandler.cpp).
Q_CORE_EXPORT double qstrtod(const char* s00, char const** se, bool* ok);
// '0' is 0x30 and '9' is 0x39
static inline bool isDigit(ushort ch)
{
static quint16 magic = 0x3ff;
return ((ch >> 4) == 3) && (magic >> (ch & 15));
}
static qreal toDouble(const QChar*& str)
{
const int maxLen = 255;//technically doubles can go til 308+ but whatever
char temp[maxLen + 1];
int pos = 0;
if (*str == QLatin1Char('-')) {
temp[pos++] = '-';
++str;
}
else if (*str == QLatin1Char('+')) {
++str;
}
while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
if (*str == QLatin1Char('.') && pos < maxLen) {
temp[pos++] = '.';
++str;
}
while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
bool exponent = false;
if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
exponent = true;
temp[pos++] = 'e';
++str;
if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
}
temp[pos] = '\0';
qreal val;
if (!exponent && pos < 10) {
int ival = 0;
const char* t = temp;
bool neg = false;
if (*t == '-') {
neg = true;
++t;
}
while (*t && *t != '.') {
ival *= 10;
ival += (*t) - '0';
++t;
}
if (*t == '.') {
++t;
int div = 1;
while (*t) {
ival *= 10;
ival += (*t) - '0';
div *= 10;
++t;
}
val = ((qreal)ival) / ((qreal)div);
}
else {
val = ival;
}
if (neg)
val = -val;
}
else {
bool ok = false;
val = qstrtod(temp, nullptr, &ok);
}
return val;
}
static inline void parseNumbersArray(const QChar*& str, QVarLengthArray<qreal, 8>& points)
{
while (str->isSpace())
++str;
while (isDigit(str->unicode()) ||
*str == QLatin1Char('-') || *str == QLatin1Char('+') ||
*str == QLatin1Char('.')) {
points.append(toDouble(str));
while (str->isSpace())
++str;
if (*str == QLatin1Char(','))
++str;
//eat the rest of space
while (str->isSpace())
++str;
}
}
static void pathArcSegment(QPainterPath& path,
qreal xc, qreal yc,
qreal th0, qreal th1,
qreal rx, qreal ry, qreal xAxisRotation)
{
qreal sinTh, cosTh;
qreal a00, a01, a10, a11;
qreal x1, y1, x2, y2, x3, y3;
qreal t;
qreal thHalf;
sinTh = qSin(qDegreesToRadians(xAxisRotation));
cosTh = qCos(qDegreesToRadians(xAxisRotation));
a00 = cosTh * rx;
a01 = -sinTh * ry;
a10 = sinTh * rx;
a11 = cosTh * ry;
thHalf = 0.5 * (th1 - th0);
t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
x1 = xc + qCos(th0) - t * qSin(th0);
y1 = yc + qSin(th0) + t * qCos(th0);
x3 = xc + qCos(th1);
y3 = yc + qSin(th1);
x2 = x3 + t * qSin(th1);
y2 = y3 - t * qCos(th1);
path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
}
void QQuickSvgParser::pathArc(QPainterPath& path,
qreal rx,
qreal ry,
qreal x_axis_rotation,
int large_arc_flag,
int sweep_flag,
qreal x,
qreal y,
qreal curx, qreal cury)
{
qreal sin_th, cos_th;
qreal a00, a01, a10, a11;
qreal x0, y0, x1, y1, xc, yc;
qreal d, sfactor, sfactor_sq;
qreal th0, th1, th_arc;
int i, n_segs;
qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
rx = qAbs(rx);
ry = qAbs(ry);
sin_th = qSin(qDegreesToRadians(x_axis_rotation));
cos_th = qCos(qDegreesToRadians(x_axis_rotation));
dx = (curx - x) / 2.0;
dy = (cury - y) / 2.0;
dx1 = cos_th * dx + sin_th * dy;
dy1 = -sin_th * dx + cos_th * dy;
Pr1 = rx * rx;
Pr2 = ry * ry;
Px = dx1 * dx1;
Py = dy1 * dy1;
/* Spec : check if radii are large enough */
check = Px / Pr1 + Py / Pr2;
if (check > 1) {
rx = rx * qSqrt(check);
ry = ry * qSqrt(check);
}
a00 = cos_th / rx;
a01 = sin_th / rx;
a10 = -sin_th / ry;
a11 = cos_th / ry;
x0 = a00 * curx + a01 * cury;
y0 = a10 * curx + a11 * cury;
x1 = a00 * x + a01 * y;
y1 = a10 * x + a11 * y;
/* (x0, y0) is current point in transformed coordinate space.
(x1, y1) is new point in transformed coordinate space.
The arc fits a unit-radius circle in this space.
*/
d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
sfactor_sq = 1.0 / d - 0.25;
if (sfactor_sq < 0) sfactor_sq = 0;
sfactor = qSqrt(sfactor_sq);
if (sweep_flag == large_arc_flag) sfactor = -sfactor;
xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
/* (xc, yc) is center of the circle. */
th0 = qAtan2(y0 - yc, x0 - xc);
th1 = qAtan2(y1 - yc, x1 - xc);
th_arc = th1 - th0;
if (th_arc < 0 && sweep_flag)
th_arc += 2 * M_PI;
else if (th_arc > 0 && !sweep_flag)
th_arc -= 2 * M_PI;
n_segs = qCeil(qAbs(th_arc / (M_PI * 0.5 + 0.001)));
for (i = 0; i < n_segs; i++) {
pathArcSegment(path, xc, yc,
th0 + i * th_arc / n_segs,
th0 + (i + 1) * th_arc / n_segs,
rx, ry, x_axis_rotation);
}
}
bool QQuickSvgParser::parsePathDataFast(const QString& dataStr, QPainterPath& path)
{
qreal x0 = 0, y0 = 0; // starting point
qreal x = 0, y = 0; // current point
char lastMode = 0;
QPointF ctrlPt;
const QChar* str = dataStr.constData();
const QChar* end = str + dataStr.size();
while (str != end) {
while (str->isSpace())
++str;
QChar pathElem = *str;
++str;
QVarLengthArray<qreal, 8> arg;
parseNumbersArray(str, arg);
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
const qreal* num = arg.constData();
int count = arg.count();
while (count > 0) {
qreal offsetX = x; // correction offsets
qreal offsetY = y; // for relative commands
switch (pathElem.unicode()) {
case 'm': {
if (count < 2) {
num++;
count--;
break;
}
x = x0 = num[0] + offsetX;
y = y0 = num[1] + offsetY;
num += 2;
count -= 2;
path.moveTo(x0, y0);
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
// the subsequent pairs shall be treated as implicit 'lineto' commands.
pathElem = QLatin1Char('l');
}
break;
case 'M': {
if (count < 2) {
num++;
count--;
break;
}
x = x0 = num[0];
y = y0 = num[1];
num += 2;
count -= 2;
path.moveTo(x0, y0);
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
// the subsequent pairs shall be treated as implicit 'lineto' commands.
pathElem = QLatin1Char('L');
}
break;
case 'z':
case 'Z': {
x = x0;
y = y0;
count--; // skip dummy
num++;
path.closeSubpath();
}
break;
case 'l': {
if (count < 2) {
num++;
count--;
break;
}
x = num[0] + offsetX;
y = num[1] + offsetY;
num += 2;
count -= 2;
path.lineTo(x, y);
}
break;
case 'L': {
if (count < 2) {
num++;
count--;
break;
}
x = num[0];
y = num[1];
num += 2;
count -= 2;
path.lineTo(x, y);
}
break;
case 'h': {
x = num[0] + offsetX;
num++;
count--;
path.lineTo(x, y);
}
break;
case 'H': {
x = num[0];
num++;
count--;
path.lineTo(x, y);
}
break;
case 'v': {
y = num[0] + offsetY;
num++;
count--;
path.lineTo(x, y);
}
break;
case 'V': {
y = num[0];
num++;
count--;
path.lineTo(x, y);
}
break;
case 'c': {
if (count < 6) {
num += count;
count = 0;
break;
}
QPointF c1(num[0] + offsetX, num[1] + offsetY);
QPointF c2(num[2] + offsetX, num[3] + offsetY);
QPointF e(num[4] + offsetX, num[5] + offsetY);
num += 6;
count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
break;
}
case 'C': {
if (count < 6) {
num += count;
count = 0;
break;
}
QPointF c1(num[0], num[1]);
QPointF c2(num[2], num[3]);
QPointF e(num[4], num[5]);
num += 6;
count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
break;
}
case 's': {
if (count < 4) {
num += count;
count = 0;
break;
}
QPointF c1;
if (lastMode == 'c' || lastMode == 'C' ||
lastMode == 's' || lastMode == 'S')
c1 = QPointF(2 * x - ctrlPt.x(), 2 * y - ctrlPt.y());
else
c1 = QPointF(x, y);
QPointF c2(num[0] + offsetX, num[1] + offsetY);
QPointF e(num[2] + offsetX, num[3] + offsetY);
num += 4;
count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
break;
}
case 'S': {
if (count < 4) {
num += count;
count = 0;
break;
}
QPointF c1;
if (lastMode == 'c' || lastMode == 'C' ||
lastMode == 's' || lastMode == 'S')
c1 = QPointF(2 * x - ctrlPt.x(), 2 * y - ctrlPt.y());
else
c1 = QPointF(x, y);
QPointF c2(num[0], num[1]);
QPointF e(num[2], num[3]);
num += 4;
count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
break;
}
case 'q': {
if (count < 4) {
num += count;
count = 0;
break;
}
QPointF c(num[0] + offsetX, num[1] + offsetY);
QPointF e(num[2] + offsetX, num[3] + offsetY);
num += 4;
count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
break;
}
case 'Q': {
if (count < 4) {
num += count;
count = 0;
break;
}
QPointF c(num[0], num[1]);
QPointF e(num[2], num[3]);
num += 4;
count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
break;
}
case 't': {
if (count < 2) {
num += count;
count = 0;
break;
}
QPointF e(num[0] + offsetX, num[1] + offsetY);
num += 2;
count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
c = QPointF(2 * x - ctrlPt.x(), 2 * y - ctrlPt.y());
else
c = QPointF(x, y);
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
break;
}
case 'T': {
if (count < 2) {
num += count;
count = 0;
break;
}
QPointF e(num[0], num[1]);
num += 2;
count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
c = QPointF(2 * x - ctrlPt.x(), 2 * y - ctrlPt.y());
else
c = QPointF(x, y);
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
break;
}
case 'a': {
if (count < 7) {
num += count;
count = 0;
break;
}
qreal rx = (*num++);
qreal ry = (*num++);
qreal xAxisRotation = (*num++);
qreal largeArcFlag = (*num++);
qreal sweepFlag = (*num++);
qreal ex = (*num++) + offsetX;
qreal ey = (*num++) + offsetY;
count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
int(sweepFlag), ex, ey, curx, cury);
x = ex;
y = ey;
}
break;
case 'A': {
if (count < 7) {
num += count;
count = 0;
break;
}
qreal rx = (*num++);
qreal ry = (*num++);
qreal xAxisRotation = (*num++);
qreal largeArcFlag = (*num++);
qreal sweepFlag = (*num++);
qreal ex = (*num++);
qreal ey = (*num++);
count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
int(sweepFlag), ex, ey, curx, cury);
x = ex;
y = ey;
}
break;
default:
return false;
}
lastMode = pathElem.toLatin1();
}
}
return true;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,64 @@
#pragma once
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Quick 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 QQUICKSVGPARSER_P_H
#define QQUICKSVGPARSER_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 "qtquickglobal_p.h"
#include <QtCore/qstring.h>
#include <QtGui/qpainterpath.h>
QT_BEGIN_NAMESPACE
namespace QQuickSvgParser
{
bool parsePathDataFast(const QString& dataStr, QPainterPath& path);
Q_QUICK_PRIVATE_EXPORT void pathArc(QPainterPath& path, qreal rx, qreal ry, qreal x_axis_rotation,
int large_arc_flag, int sweep_flag, qreal x, qreal y, qreal curx,
qreal cury);
}
QT_END_NAMESPACE
#endif // QQUICKSVGPARSER_P_H

View File

@ -0,0 +1,56 @@
#pragma once
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick 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 QTQUICKGLOBAL_H
#define QTQUICKGLOBAL_H
#include <QtQml/qtqmlglobal.h>
#include <QtGui/qtguiglobal.h>
#include <QtQuick/qtquick-config.h>
QT_BEGIN_NAMESPACE
#ifndef QT_STATIC
# if defined(QT_BUILD_QUICK_LIB)
# define Q_QUICK_EXPORT Q_DECL_EXPORT
# else
# define Q_QUICK_EXPORT Q_DECL_IMPORT
# endif
#else
# define Q_QUICK_EXPORT
#endif
QT_END_NAMESPACE
#endif // QTQUICKGLOBAL_H

View File

@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick 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 QTQUICKGLOBAL_P_H
#define QTQUICKGLOBAL_P_H
//#include <QtQml/private/qtqmlglobal_p.h>
//#include <QtGui/private/qtguiglobal_p.h>
//#include <QtQuick/private/qtquick-config_p.h>
#include <QtCore/qloggingcategory.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 "qtquickglobal.h"
#define Q_QUICK_PRIVATE_EXPORT Q_QUICK_EXPORT
//void Q_QUICK_PRIVATE_EXPORT qml_register_types_QtQuick();
//QT_BEGIN_NAMESPACE
//void QQuick_initializeProviders();
//void QQuick_deinitializeProviders();
Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH)
Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE)
Q_DECLARE_LOGGING_CATEGORY(DBG_FOCUS)
Q_DECLARE_LOGGING_CATEGORY(DBG_DIRTY)
QT_END_NAMESPACE
#endif // QTQUICKGLOBAL_P_H