Compare commits

..

2 Commits

12 changed files with 303 additions and 42 deletions

View File

@ -2,9 +2,12 @@
#include <QFile>
#include "../ThirdPartyLib/qquick/qquicksvgparser_p.h"
#include <QPolygonF>
#include <iostream>
using std::map;
using std::vector;
using std::reverse;
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
QFile file(filePath);
@ -46,12 +49,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa
}
}
}
qDebug() << painterPath;
file.close();
return true;
}
QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
QMap<QString, QString> resStyleMap;
for (auto& attr : style.split(';')) {
if (attr.isEmpty() || attr.trimmed() == "") continue;
@ -62,7 +65,7 @@ QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
return resStyleMap;
}
QPolygonF SvgFileLoader::transformPoints(QString points) {
QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
QPolygonF resPointVector;
QPointF point(0, 0);
bool isX = true;
@ -80,10 +83,58 @@ QPolygonF SvgFileLoader::transformPoints(QString points) {
return resPointVector;
}
void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) {
QTransform trans;
QStringList ops = transformStyle.split(')');
reverse(ops.begin(), ops.end());
vector<double> numbers;
for (auto op : ops) {
op = op.simplified();
if (op.isEmpty()) continue;
QString type = (*op.split('(').begin()).trimmed();
QString numStr = (*op.split('(').rbegin()).trimmed() + ',';
QString tmpNum = "";
for (auto c : numStr) {
if (isdigit(c.toLatin1())) {
tmpNum += c;
}
else {
if (c == ',' && tmpNum.size() == 0) {
numbers.push_back(0);
}
else if (tmpNum.size() > 0) {
numbers.push_back(tmpNum.toDouble());
}
tmpNum.clear();
}
}
qDebug() << type << "///:" << numbers;
if (type == "translate") {
trans.translate(numbers[0], numbers[1]);
}
if (type == "scale") {
trans.scale(numbers[0], numbers[1]);
}
if (type == "rotate") {
trans.translate(numbers[1], numbers[2]);
trans.rotate(numbers[0]);
trans.translate(-numbers[1], -numbers[2]);
}
if (type == "skewX") {
trans.shear(numbers[0], 0);
}
if (type == "skewY") {
trans.shear(0, numbers[1]);
}
}
painterPath = trans.map(painterPath);
qDebug() << painterPath;
}
void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("style")) {
styleMap = transformStyle(attr.value().toLatin1());
styleMap = handleAttrStyle(attr.value().toLatin1());
}
else {
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -94,22 +145,33 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
}
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("d")) {
QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), painterPath);
QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), elementPainterPath);
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
QMap<QString, QString> labelStyle;
QPainterPath elementPainterPath;
QString transformStyle = "";
double xBegin = 0, yBegin = 0, width = 0, height = 0;;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("x")) {
@ -122,17 +184,26 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
height = attr.value().toDouble();
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
painterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
elementPainterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, r = 0;
for (auto& attr : xmlReader->attributes()) {
@ -144,18 +215,28 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
r = attr.value().toDouble();
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
elementPainterPath.addEllipse(cx, cy, r, r);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
//addEllipse(cx, cy, r, r, painterPath);
painterPath.addEllipse(cx, cy, r, r);
}
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, rx = 0, ry = 0;
for (auto& attr : xmlReader->attributes()) {
@ -168,7 +249,10 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} else if (attr.name().toString() == QLatin1String("ry")) {
rx = attr.value().toDouble();
} else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -176,49 +260,73 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
}
qDebug() << labelStyle;
//addEllipse(cx, cy, rx, ry, painterPath);
painterPath.addEllipse(cx, cy, rx, ry);
elementPainterPath.addEllipse(cx, cy, rx, ry);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1());
painterPath.addPolygon(points);
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
elementPainterPath.addPolygon(points);
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1());
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
//points.push_back(*points.begin());
painterPath.addPolygon(points);
painterPath.closeSubpath();
elementPainterPath.addPolygon(points);
elementPainterPath.closeSubpath();
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = transformStyle(attr.value().toLatin1());
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == "transform") {
transformStyle = attr.value().toLatin1();
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
/*
void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) {
double k = w / 0.75;
painterPath.moveTo(x, y - h);
painterPath.cubicTo(QPointF(x + k, y - h), QPointF(x + k, y + h), QPointF(x, y + h));
painterPath.cubicTo(QPointF(x - k, y + h), QPointF(x - k, y - h), QPointF(x, y - h));
painterPath.closeSubpath();
}
}
*/

View File

@ -13,9 +13,10 @@ private:
bool existFatherLabelG;
QMap<QString, QString> styleMap;
std::shared_ptr<QXmlStreamReader> xmlReader;
QPolygonF transformPoints(QString points);
QMap<QString, QString> transformStyle(QString style);
void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
QPolygonF handleAttrPoints(QString points);
QMap<QString, QString> handleAttrStyle(QString style);
void handleAttrTransform(QString transformStyle, QPainterPath& painterPath);
//void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
void handleLabelG(QPainterPath& painterPath);
void handleLabelPath(QPainterPath& painterPath);
void handleLabelRect(QPainterPath& painterPath);

View File

@ -22,6 +22,12 @@ Point CubicBezier::calculateControlPoint(Point a, Point b) {
};
}
double CubicBezier::ValueOfFunctionS(double t) {
double dxt = -3 * vX[0] * (1 - t) * (1 - t) + 3 * vX[1] * (1 - t) * (1 - 3 * t) + 3 * vX[2] * t * (2 - 3 * t) + 3 * vX[3] * t * t;
double dyt = -3 * vY[0] * (1 - t) * (1 - t) + 3 * vY[1] * (1 - t) * (1 - 3 * t) + 3 * vY[2] * t * (2 - 3 * t) + 3 * vY[3] * t * t;
return sqrt(dxt * dxt + dyt * dyt);
}
void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) {
double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]);
if (fabs(a) > eps) {
@ -55,20 +61,26 @@ void CubicBezier::transformToCubic() {
}
void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) {
LinePtr Lf(new CubicBezier());
float pt = 1 - t;
Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t);
Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t);
Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t);
Lf->push_back(getPointByIndex(0));
Lf->push_back(pointF);
Lf->push_back(getPointByT(pointF, pointG, t));
Lf->push_back(pointE);
res.push_back(Lf);
vector<Point> vP; vP.clear();
vP.push_back(getPointByIndex(0));
vP.push_back(pointF);
vP.push_back(getPointByT(pointF, pointG, t));
vP.push_back(pointE);
LinePtr lf(new CubicBezier(vP));
double totalLen = getIntegralByT(1), len = getIntegralByT(t);
if (totalLen <= eps) return;
double ratePoint = (1 - len / totalLen) * rate.first + len / totalLen * rate.second;
lf->setRate({ rate.first, ratePoint });
res.push_back(lf);
setPointByIndex(0, pointE);
setPointByIndex(1, getPointByT(pointG, pointH, t));
setPointByIndex(2, pointH);
updateLeftType();
setRate({ ratePoint, rate.second });
}
void CubicBezier::monotonization(vector <LinePtr>& res) {
@ -120,4 +132,4 @@ int CubicBezier::judgeOneSideIntersection(double xy, double l, double r, bool is
double CubicBezier::getMinDistanceFromPoint(Point p) {
return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd());
}
}

View File

@ -11,12 +11,14 @@ namespace Renderer
static Point calculateControlPoint(Point a, Point b);
static void findPointsOfDivison(std::vector<double>& p, std::vector<double>& res);
void splitBezierCubic(double t, std::vector<LinePtr>& res);
public:
virtual double findTByValue(double value, bool isY);
virtual void monotonization(std::vector <LinePtr>& res);
virtual double getLineValueByT(double t, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t);
void transformToCubic();
};
}

View File

@ -1,4 +1,5 @@
#include "Line.h"
#include <glm/detail/func_packing.hpp>
using namespace Renderer;
using std::vector;
using std::pair;
@ -14,14 +15,29 @@ Line::Line(vector<Point> Vp) {
vX.push_back(now.x);
vY.push_back(now.y);
}
updateLeftType();
rate = { 0, 1 };
}
bool Line::updateLeftType() {
if (*vY.rbegin() < vY[0]) leftType = 0;
else leftType = 1;
return true;
}
int Line::size() {
return siz;
}
bool Line::setRate(std::pair<double, double> inRate) {
rate = inRate;
return true;
}
uint Line::getRate() {
return glm::packUnorm2x16(glm::vec2(rate.first, rate.second));
}
vector<Point> Line::toPointVector() const {
vector<Point> vL;
for (int i = 0; i < siz; i++) {
@ -151,4 +167,27 @@ bool Line::judgeIntersectionWithWidth(QVector4D bound, double width, int type) {
|| judgeOneSideIntersectionWithWidth(bound.w(), bound.x(), bound.z(), true, width, type)
|| judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type)
|| judgeOneSideIntersectionWithWidth(bound.z(), bound.y(), bound.w(), false, width, type);
}
double Line::getIntegralByT(double t) {
double T[12][12], err = 1, S = 0, tmpPow4 = 1;
T[1][1] = t * (ValueOfFunctionS(t) + ValueOfFunctionS(0)) / 2;
int n = 1, k = 0;
while (err > eps) {
++k; S = 0;
for (int i = 1; i <= n; i++) {
double x = t * (2 * i - 1) / 2;
S = S + ValueOfFunctionS(x);
}
tmpPow4 = 1;
T[k + 1][1] = (T[k][1] + t * S) / 2;
for (int m = 1; m <= k; m++) {
tmpPow4 *= 4;
T[k + 1][m + 1] = (tmpPow4 * T[k + 1][m] - T[k][m]) / (tmpPow4 - 1);
}
err = fabs(T[k + 1][k + 1] - T[k + 1][k]);
n <<= 1; t = t / 2;
if (k >= 8) break;
}
return T[k + 1][k + 1];
}

View File

@ -49,21 +49,28 @@ namespace Renderer
protected:
std::vector<double> vX, vY;
int siz, leftType;
std::pair<double, double> rate;
public:
typedef std::shared_ptr<Line> LinePtr;
Line() :siz(0) {}
Line() : siz(0), leftType(0), rate({0, 1}) {}
Line(std::vector<Point> Vp);
int size();
bool setRate(std::pair<double, double> inRate);
uint getRate();
void clear();
Point getBegin();
Point getEnd();
int direction(bool isY);
bool updateLeftType();
virtual double getLineValueByT(double t, bool isY) = 0;
// s = sqrt(x^2+y^2);
virtual double ValueOfFunctionS(double t) = 0;
virtual void monotonization(std::vector <LinePtr>& res) = 0;
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0;
virtual double getMinDistanceFromPoint(Point p) = 0;
bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type);
virtual double findTByValue(double value, bool isY) = 0;
double getIntegralByT(double t);
bool judgeIntersectionWithWidth(QVector4D bound, double width, int type);
bool judgeIntersection(QVector4D bound);
int getPointSideOfLine(Point p);

View File

@ -108,15 +108,30 @@ void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_p
}
void LineTree::simplifyLineVector() {
bool canPut = false;
GLuint index = 0;
numLine = allLines.size();
for (auto& nowLine : allLines) {
PointVector pointVector = nowLine->toPointVector();
canPut = false;
index = 0;
for (Point& p : pointVector) {
int pointIndex = getPointIndex(p);
lineIndexs.push_back(pointIndex);
if (pointVector.size() == 2)
lineIndexs.push_back(pointIndex);
if (pointVector.size() == 2) {
index = (pointIndex << 16) + pointIndex;
lineIndexs.push_back(index);
}
else {
index <<= 16;
index += pointIndex;
if (canPut) {
lineIndexs.push_back(index);
index = 0;
}
canPut = !canPut;
}
}
lineIndexs.push_back(nowLine->getRate());
}
}
@ -237,15 +252,15 @@ vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
for (auto& vectorIter : tmpPoints) {
resPoints.push_back(vectorIter.second.x);
resPoints.push_back(vectorIter.second.y);
vectorIter.second.show();
std::cout << '\n';
//vectorIter.second.show();
//std::cout << '\n';
}
// Ïß¼¯
for (auto& nowLineIndex : lineIndexs) {
resLines.push_back(nowLineIndex);
std::cout << nowLineIndex << ' ';
//std::cout << nowLineIndex << ' ';
}
std::cout << '\n';
//std::cout << '\n';
// ·µ»Ø¹¹ÔìBvhTreeÊý¾Ý
vector<BvhTreeData> resBvhTreeData;
for (auto& nowTreeNode : restOfTreeNodes) {
@ -253,13 +268,13 @@ vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
oneData.leftSon = resLines.size();
oneData.rightSon = 0;
oneData.bound = nowTreeNode.bound;
std::cout << nowTreeNode.lineSet.size() << ' ';
//std::cout << nowTreeNode.lineSet.size() << ' ';
resLines.push_back(nowTreeNode.lineSet.size());
for (auto& lineIndex : nowTreeNode.lineSet) {
resLines.push_back(lineIndex);
std::cout << lineIndex << ' ';
//std::cout << lineIndex << ' ';
}
std::cout << '\n';
//std::cout << '\n';
resBvhTreeData.push_back(oneData);
}
return resBvhTreeData;

View File

@ -14,6 +14,10 @@ double StraightLine::getLineValueByT(double t, bool isY) {
return t * (valueEnd - valueBegin) + valueBegin;
}
double StraightLine::ValueOfFunctionS(double t) {
return sqrt((vX[1] - vX[0]) * (vX[1] - vX[0]) + (vY[1] - vY[0]) * (vY[1] - vY[0]));
}
double StraightLine::findTByValue(double value, bool isY) {
Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1);
if (!isY) {

View File

@ -11,5 +11,6 @@ namespace Renderer
virtual double findTByValue(double value, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t);
};
}

View File

@ -3,6 +3,7 @@
#include <QtWidgets/QApplication>
#include "ElementRendererTest.h"
#include "Renderer/Painting/ElementStyle.h"
#include <util/SvgFileLoader.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer;
@ -197,4 +198,5 @@ namespace UnitTest
a.exec();
}
};
}

View File

@ -3,12 +3,43 @@
#include <QGuiApplication>
#include <QtWidgets/QApplication>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <util/SvgFileLoader.h>
#include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest
{
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
switch (type)
{
case QtInfoMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
break;
case QtDebugMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
case QtWarningMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
break;
case QtCriticalMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
break;
case QtFatalMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
break;
}
Logger::WriteMessage(std::format("{}({},{}) {}\n",
QString(context.file).splitRef("\\").back().toLocal8Bit().data(),
context.line,
QString(context.function).splitRef("(").first().split(" ").back().split(":").back().toLocal8Bit().data(),
msg.toStdString()).c_str());
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
TEST_CLASS(UnitTest)
{
public:
@ -31,4 +62,37 @@ namespace UnitTest
a.exec();
}
};
TEST_CLASS(SvgLoaderTest)
{
public:
TEST_METHOD(LoadSvg)
{
qInstallMessageHandler(messageHandler);
QPainterPath painterPath;
SvgFileLoader svgloader;
svgloader.loadSvgFile("D:\\BigC\\Project\\ArchitectureColoredPainting\\svg\\test.svg", painterPath);
}
};
TEST_CLASS(CubicBezierTest)
{
public:
TEST_METHOD(CubicIntegral)
{
qInstallMessageHandler(messageHandler);
std::shared_ptr<Renderer::Line> line(new Renderer::CubicBezier());
line->push_back({ -1, -1 });
line->push_back({ -1, 1 });
line->push_back({ 1, 1 });
line->push_back({ 1, -1 });
vector<std::shared_ptr<Renderer::Line>> outLines;
line->monotonization(outLines);
for (auto line : outLines) {
qDebug() << line->getRate();
}
}
};
}

6
svg/test.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="300" height="100"
style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"
transform="translate(50 20)"/>
</svg>

After

Width:  |  Height:  |  Size: 191 B