引入了第三方库
parent
fe6e10c882
commit
dc89e02515
|
@ -32,7 +32,7 @@
|
|||
</ImportGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||
<QtInstall>5.15.2_msvc2019_64</QtInstall>
|
||||
<QtModules>core;gui;widgets;winextras</QtModules>
|
||||
<QtModules>core;xml;gui;svg;widgets;winextras</QtModules>
|
||||
<QtBuildConfig>debug</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||
|
@ -105,6 +105,7 @@
|
|||
<ClCompile Include="src\Editor\LayerManager.cpp" />
|
||||
<ClCompile Include="src\Editor\LayerWrapper.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\main.cpp" />
|
||||
<ClCompile Include="src\MainWindow.cpp" />
|
||||
|
@ -129,6 +130,7 @@
|
|||
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
|
||||
<ClCompile Include="src\SvgParser.cpp" />
|
||||
<ClCompile Include="src\TitleWidget.cpp" />
|
||||
<ClCompile Include="src\Editor\third-party modules\SvgHelper.cpp" />
|
||||
<QtRcc Include="MainWindow.qrc" />
|
||||
<QtUic Include="EditorWidget.ui" />
|
||||
<QtUic Include="FramelessWindow.ui" />
|
||||
|
@ -158,6 +160,10 @@
|
|||
<None Include="Shaders\ssgi.comp" />
|
||||
</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" />
|
||||
<ClInclude Include="src\Editor\ElementManager.h" />
|
||||
<ClInclude Include="src\Editor\GraphicElement.h" />
|
||||
|
|
|
@ -147,6 +147,12 @@
|
|||
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp">
|
||||
<Filter>Source Files\Renderer\Painting</Filter>
|
||||
</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>
|
||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||
|
@ -312,6 +318,18 @@
|
|||
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h">
|
||||
<Filter>Header Files\Renderer\Painting</Filter>
|
||||
</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>
|
||||
<QtRcc Include="MainWindow.qrc">
|
||||
|
|
|
@ -1,75 +1,19 @@
|
|||
#include "GraphicElement.h"
|
||||
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
|
||||
{
|
||||
return painterPath;
|
||||
}
|
||||
// TODO
|
||||
void SimpleElement::pathOperate(QJsonArray paths)
|
||||
|
||||
void SimpleElement::loadSvgFile(const QString& filePath)
|
||||
{
|
||||
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);
|
||||
// TODO
|
||||
}
|
||||
|
||||
SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource)
|
||||
{
|
||||
painterPath.clear();
|
||||
elementType = ElementTypeStringValue::enumType(jsonSource.value("type").toString().toStdString());
|
||||
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;
|
||||
}
|
||||
loadSvgFile(jsonSource.value("data").toObject().value("include").toString());
|
||||
}
|
||||
|
||||
GroupElement::GroupElement(FolderLayerWrapper *sourceLayer)
|
||||
|
|
|
@ -8,26 +8,10 @@ class LayerWrapper;
|
|||
class LeafLayerWrapper;
|
||||
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
|
||||
{
|
||||
public:
|
||||
QString name="";
|
||||
virtual QPainterPath getPaintObject() const = 0;
|
||||
};
|
||||
class SimpleElement : public GraphicElement
|
||||
|
@ -35,10 +19,7 @@ class SimpleElement : public GraphicElement
|
|||
private:
|
||||
QJsonObject jsonSource;
|
||||
QPainterPath painterPath;
|
||||
ElementType elementType;
|
||||
void pathOperate(QJsonArray paths);
|
||||
void polygonOperate(QJsonArray points);
|
||||
void roundOperate(QJsonObject json);
|
||||
void loadSvgFile(const QString& filePath);
|
||||
|
||||
public:
|
||||
SimpleElement(QJsonObject jsonSource);
|
||||
|
|
|
@ -35,7 +35,7 @@ void PreviewWindow::initializeGL()
|
|||
initializeOpenGLFunctions();
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
#include "./third-party modules/qquick/qquicksvgparser_p.h"
|
||||
void PreviewWindow::paintGL()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue