实现线的平头样式
parent
315083cd52
commit
3fe7bab969
|
@ -896,39 +896,39 @@ bool angleLargeThanPi(vec2 a, vec2 b)
|
||||||
void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
elementColor = vec4(1);
|
elementColor = vec4(1);
|
||||||
metallicRoughness = vec2(0.8);
|
metallicRoughness = vec2(0.8);
|
||||||
uint headUint = floatBitsToUint(style[styleIndex+1]);
|
uint headUint = floatBitsToUint(style[styleIndex + 1]);
|
||||||
vec4 head = unpackUnorm4x8(headUint);
|
vec4 head = unpackUnorm4x8(headUint);
|
||||||
switch (int(head.a*100)%10)
|
switch (int(head.a * 100) % 10)
|
||||||
//switch (2)
|
// switch (2)
|
||||||
{
|
{
|
||||||
/// Plain
|
/// Plain
|
||||||
case 0: {
|
case 0: {
|
||||||
metallicRoughness = head.rg;
|
metallicRoughness = head.rg;
|
||||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+2])).rgb, 1);
|
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 2])).rgb, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/// RadialGradient
|
/// RadialGradient
|
||||||
case 1: {
|
case 1: {
|
||||||
uint size = headUint%(1<<15);
|
uint size = headUint % (1 << 15);
|
||||||
bool gradual = (headUint&(1<<15))!=0;
|
bool gradual = (headUint & (1 << 15)) != 0;
|
||||||
|
|
||||||
uint lastData = floatBitsToUint(style[styleIndex+2+0*2]);
|
uint lastData = floatBitsToUint(style[styleIndex + 2 + 0 * 2]);
|
||||||
float lastLevel = 0;
|
float lastLevel = 0;
|
||||||
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
|
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
|
||||||
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+3+0*2])).rgb, 1);
|
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 3 + 0 * 2])).rgb, 1);
|
||||||
|
|
||||||
for(uint i = 0; i < size; i++)
|
for (uint i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
uint data = floatBitsToUint(style[styleIndex+2+i*2]);
|
uint data = floatBitsToUint(style[styleIndex + 2 + i * 2]);
|
||||||
float level = unpackUnorm2x16(data).y;
|
float level = unpackUnorm2x16(data).y;
|
||||||
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+3+i*2])).rgb, 1);
|
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 3 + i * 2])).rgb, 1);
|
||||||
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
|
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
|
||||||
if (d <= level)
|
if (d <= level)
|
||||||
{
|
{
|
||||||
if(gradual)
|
if (gradual)
|
||||||
{
|
{
|
||||||
float a = (d-lastLevel)/(level-lastLevel);
|
float a = (d - lastLevel) / (level - lastLevel);
|
||||||
elementColor = mix(lastColor, currentColor, a);
|
elementColor = mix(lastColor, currentColor, a);
|
||||||
metallicRoughness = mix(lastMetallicRoughness, currentMetallicRoughness, a);
|
metallicRoughness = mix(lastMetallicRoughness, currentMetallicRoughness, a);
|
||||||
}
|
}
|
||||||
|
@ -969,6 +969,35 @@ void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, vec2 tangentBegin, vec2 tangentEndLast)
|
||||||
|
{
|
||||||
|
vec2 normal;
|
||||||
|
if (onVeryBegin)
|
||||||
|
{
|
||||||
|
if (endType == 0)
|
||||||
|
return true;
|
||||||
|
else if (endType == 1)
|
||||||
|
normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec2 normalLast = normalize(mat2(0, 1, -1, 0) * tangentEndLast);
|
||||||
|
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
|
||||||
|
normal = normalLast + normalNow;
|
||||||
|
}
|
||||||
|
return angleLargeThanPi(normal, localUV - p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldFillEndCap(vec2 localUV, int endType, vec2 p0, vec2 tangentEnd)
|
||||||
|
{
|
||||||
|
vec2 normal;
|
||||||
|
if (endType == 0)
|
||||||
|
return true;
|
||||||
|
else if (endType == 1)
|
||||||
|
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
|
||||||
|
return angleLargeThanPi(localUV - p0, normal);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
uvec2 pixelLocation = gl_GlobalInvocationID.xy;
|
uvec2 pixelLocation = gl_GlobalInvocationID.xy;
|
||||||
|
@ -1022,19 +1051,30 @@ void main()
|
||||||
else // Stroke
|
else // Stroke
|
||||||
{
|
{
|
||||||
float minDistance = 1e38;
|
float minDistance = 1e38;
|
||||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex+1]));
|
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex + 1]));
|
||||||
float lineType = floor(styleHead.b*10);
|
float lineType = floor(styleHead.b * 10);
|
||||||
//float lineType = 2;
|
// float lineType = 2;
|
||||||
|
int endType = int(round(styleHead.b * 100)) % 10;
|
||||||
|
//endType = 1;
|
||||||
int debugBegin = 0;
|
int debugBegin = 0;
|
||||||
|
bool onVeryBegin = false;
|
||||||
|
vec2 tangentEndLast;
|
||||||
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
|
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
|
||||||
|
// for (uint pathIndex = 0; pathIndex < 4; pathIndex++)
|
||||||
{
|
{
|
||||||
vec2 pTemp = path[pathIndex];
|
vec2 pTemp = path[pathIndex];
|
||||||
if (isinf(pTemp.x))
|
if (isinf(pTemp.x))
|
||||||
{
|
{
|
||||||
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
|
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
|
||||||
|
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||||
|
{
|
||||||
|
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
||||||
|
}
|
||||||
|
|
||||||
pBegin = path[++pathIndex];
|
pBegin = path[++pathIndex];
|
||||||
p3Last = pBegin;
|
p3Last = pBegin;
|
||||||
|
p2Last = pBegin;
|
||||||
|
onVeryBegin = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
||||||
|
@ -1043,22 +1083,24 @@ void main()
|
||||||
if (d <= strokeWidth)
|
if (d <= strokeWidth)
|
||||||
{
|
{
|
||||||
bool onBegin = distance(localUV, p[0]) <= strokeWidth && p3Last == p[0];
|
bool onBegin = distance(localUV, p[0]) <= strokeWidth && p3Last == p[0];
|
||||||
bool fill = true;
|
vec2 tangentBegin;
|
||||||
if (onBegin)
|
vec2 tangentEnd;
|
||||||
{
|
if (p[0] != p[1])
|
||||||
vec2 normalLast = normalize(mat2(0, 1, -1, 0) * (p3Last - p2Last));
|
tangentBegin = normalize(p[0] - p[1]);
|
||||||
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (p[1] - p[0]));
|
else
|
||||||
vec2 normal = normalLast + normalNow;
|
tangentBegin = normalize(p[0] - p[2]);
|
||||||
fill = angleLargeThanPi(normal, localUV - p[0]);
|
if (p[3] != p[2])
|
||||||
}
|
tangentEnd = normalize(p[3] - p[2]);
|
||||||
if (onBegin ? fill : d < minDistance)
|
else
|
||||||
|
tangentEnd = normalize(p[3] - p[1]);
|
||||||
|
|
||||||
|
if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, p3Last - p2Last)
|
||||||
|
: d < minDistance)
|
||||||
{
|
{
|
||||||
minDistance = min(minDistance, d);
|
minDistance = min(minDistance, d);
|
||||||
|
|
||||||
bool reverse = p[3].y - p[0].y < 0.;
|
bool reverse = p[3].y - p[0].y < 0.;
|
||||||
|
|
||||||
vec2 tangentBegin = normalize(p[0] - p[1]);
|
|
||||||
vec2 tangentEnd = normalize(p[3] - p[2]);
|
|
||||||
if (tangentBegin.y == 0.)
|
if (tangentBegin.y == 0.)
|
||||||
tangentBegin.y = reverse ? eps : -eps;
|
tangentBegin.y = reverse ? eps : -eps;
|
||||||
if (tangentEnd.y == 0.)
|
if (tangentEnd.y == 0.)
|
||||||
|
@ -1066,19 +1108,26 @@ void main()
|
||||||
int intTest = cubic_bezier_int_test2(localUV, p[0], p[1], p[2], p[3], reverse) +
|
int intTest = cubic_bezier_int_test2(localUV, p[0], p[1], p[2], p[3], reverse) +
|
||||||
ray_int_test(localUV, p[0], tangentBegin, reverse) +
|
ray_int_test(localUV, p[0], tangentBegin, reverse) +
|
||||||
ray_int_test(localUV, p[3], tangentEnd, reverse);
|
ray_int_test(localUV, p[3], tangentEnd, reverse);
|
||||||
if (lineType == 2 || intTest % 2 == int(lineType))
|
|
||||||
|
if (lineType == 2 || (intTest % 2 == int(lineType)))
|
||||||
{
|
{
|
||||||
hitElement = true;
|
hitElement = true;
|
||||||
//elementColor = vec4(1, 1, 0, 1);
|
// elementColor = vec4(1, 1, 0, 1);
|
||||||
vec2 metallicRoughness;
|
vec2 metallicRoughness;
|
||||||
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
|
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
|
||||||
}
|
}
|
||||||
else if (p3Last == p[0])
|
else if (p3Last == p[0])
|
||||||
hitElement = false;
|
hitElement = false;
|
||||||
}
|
}
|
||||||
|
tangentEndLast = tangentEnd;
|
||||||
}
|
}
|
||||||
p3Last = p[3];
|
p3Last = p[3];
|
||||||
p2Last = p[2];
|
p2Last = p[2];
|
||||||
|
onVeryBegin = false;
|
||||||
|
}
|
||||||
|
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
|
||||||
|
{
|
||||||
|
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hitElement)
|
if (hitElement)
|
||||||
|
|
|
@ -7,7 +7,7 @@ using Renderer::Line;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
vector<vector<Point> > PainterPathUtil::transformToLines(QPainterPath& painterPath) {
|
vector<vector<Point>> PainterPathUtil::transformToLines(QPainterPath& painterPath) {
|
||||||
vector<Point> line; line.clear();
|
vector<Point> line; line.clear();
|
||||||
vector<vector<Point> > lines; lines.clear();
|
vector<vector<Point> > lines; lines.clear();
|
||||||
QPointF startPoint(0, 0);
|
QPointF startPoint(0, 0);
|
||||||
|
@ -48,16 +48,16 @@ QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
|
||||||
vector<vector<Point> > lines = transformToLines(painterPath);
|
vector<vector<Point> > lines = transformToLines(painterPath);
|
||||||
vector<shared_ptr<Line>> linePtrVector;
|
vector<shared_ptr<Line>> linePtrVector;
|
||||||
Renderer::LineTree::monotonization(lines, linePtrVector);
|
Renderer::LineTree::monotonization(lines, linePtrVector);
|
||||||
for (auto linePtr : linePtrVector) {
|
Point lastPoint(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity());
|
||||||
|
for (auto& linePtr : linePtrVector) {
|
||||||
vector<Point> line = linePtr->toPointVector();
|
vector<Point> line = linePtr->toPointVector();
|
||||||
if (line.size() == 2) {
|
if (line[0] != lastPoint)
|
||||||
resPath.moveTo(line[0]);
|
resPath.moveTo(line[0]);
|
||||||
|
if (line.size() == 2)
|
||||||
resPath.lineTo(line[1]);
|
resPath.lineTo(line[1]);
|
||||||
}
|
else if (line.size() == 4)
|
||||||
if (line.size() == 4) {
|
|
||||||
resPath.moveTo(line[0]);
|
|
||||||
resPath.cubicTo(line[1], line[2], line[3]);
|
resPath.cubicTo(line[1], line[2], line[3]);
|
||||||
}
|
lastPoint = line.back();
|
||||||
}
|
}
|
||||||
return resPath;
|
return resPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,10 @@
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include "../Renderer/Painting/Line.h"
|
#include "../Renderer/Painting/Line.h"
|
||||||
|
|
||||||
using Renderer::Point;
|
|
||||||
|
|
||||||
class PainterPathUtil
|
class PainterPathUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::vector<std::vector<Point> > transformToLines(QPainterPath& painterPath);
|
static std::vector<std::vector<Renderer::Point> > transformToLines(QPainterPath& painterPath);
|
||||||
static QPainterPath monotonization(QPainterPath& painterPath);
|
static QPainterPath monotonization(QPainterPath& painterPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Renderer
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
|
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
|
||||||
enum class StrokeEndType { kRound = 0 };
|
enum class StrokeEndType { kRound = 0, kFlat = 1 };
|
||||||
|
|
||||||
class MaterialStyleStroke : public MaterialStyle
|
class MaterialStyleStroke : public MaterialStyle
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,11 +37,15 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
switch (element.type)
|
switch (element.type)
|
||||||
{
|
{
|
||||||
case QPainterPath::MoveToElement:
|
case QPainterPath::MoveToElement:
|
||||||
|
qDebug() << "MoveToElement";
|
||||||
|
qDebug() << element;
|
||||||
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity()));
|
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity()));
|
||||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
||||||
break;
|
break;
|
||||||
case QPainterPath::LineToElement:
|
case QPainterPath::LineToElement:
|
||||||
{
|
{
|
||||||
|
qDebug() << "LineToElement";
|
||||||
|
qDebug() << element;
|
||||||
glm::vec2 end = glm::vec2(element.x, element.y);
|
glm::vec2 end = glm::vec2(element.x, element.y);
|
||||||
glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
|
glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
|
||||||
pathBuffer.push_back(mid);
|
pathBuffer.push_back(mid);
|
||||||
|
@ -50,8 +54,24 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QPainterPath::CurveToElement:
|
case QPainterPath::CurveToElement:
|
||||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
{
|
||||||
|
qDebug() << "CurveToElement";
|
||||||
|
qDebug() << element;
|
||||||
|
glm::vec2 p1 = glm::vec2(element.x, element.y);
|
||||||
|
element = path.elementAt(++i);
|
||||||
|
qDebug() << element;
|
||||||
|
glm::vec2 p2 = glm::vec2(element.x, element.y);
|
||||||
|
element = path.elementAt(++i);
|
||||||
|
qDebug() << element;
|
||||||
|
glm::vec2 p3 = glm::vec2(element.x, element.y);
|
||||||
|
if (p3 != pathBuffer.back())
|
||||||
|
{
|
||||||
|
pathBuffer.push_back(p1);
|
||||||
|
pathBuffer.push_back(p2);
|
||||||
|
pathBuffer.push_back(p3);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case QPainterPath::CurveToDataElement:
|
case QPainterPath::CurveToDataElement:
|
||||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
||||||
break;
|
break;
|
||||||
|
|
14
README.md
14
README.md
|
@ -23,5 +23,17 @@
|
||||||
|
|
||||||
已实现由图元数据建立完整彩绘编码
|
已实现由图元数据建立完整彩绘编码
|
||||||
|
|
||||||
已实现面的纯色样式,线的纯色、径向渐变/分层、单侧等样式
|
#### 已实现的图元样式(MaterialStyle)
|
||||||
|
|
||||||
|
##### 面(MaterialStyleFill)
|
||||||
|
|
||||||
|
纯色
|
||||||
|
|
||||||
|
##### 线(MaterialStyleStroke)
|
||||||
|
|
||||||
|
双侧/左侧/右侧
|
||||||
|
|
||||||
|
圆头/平头
|
||||||
|
|
||||||
|
纯色/渐变/分层
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,116 @@ using namespace Renderer;
|
||||||
|
|
||||||
namespace UnitTest
|
namespace UnitTest
|
||||||
{
|
{
|
||||||
TEST_CLASS(ElementRendererTest)
|
TEST_CLASS(ElementRendererStokeTypeTest)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TEST_METHOD(TestBothSidesRound)
|
||||||
|
{
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
|
char* argv[] = { (char*)"" };
|
||||||
|
int argc = 1;
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
std::map<float, Material> materialMap = {
|
||||||
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
|
TEST_METHOD(TestBothSidesFlat)
|
||||||
|
{
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
|
char* argv[] = { (char*)"" };
|
||||||
|
int argc = 1;
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
std::map<float, Material> materialMap = {
|
||||||
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kFlat,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
|
TEST_METHOD(TestLeftSideRound)
|
||||||
|
{
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
|
char* argv[] = { (char*)"" };
|
||||||
|
int argc = 1;
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
std::map<float, Material> materialMap = {
|
||||||
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kLeftSide, StrokeEndType::kRound,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
|
TEST_METHOD(TestLeftSideFlat)
|
||||||
|
{
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
|
char* argv[] = { (char*)"" };
|
||||||
|
int argc = 1;
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
std::map<float, Material> materialMap = {
|
||||||
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kLeftSide, StrokeEndType::kFlat,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CLASS(ElementRendererStokeMaterialTest)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TEST_METHOD(TestStrokePlain)
|
TEST_METHOD(TestStrokePlain)
|
||||||
|
@ -20,7 +129,15 @@ namespace UnitTest
|
||||||
char* argv[] = { (char*)"" };
|
char* argv[] = { (char*)"" };
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
Renderer::ElementStyleStrokeDemo style(2);
|
class StyleStrokePlain : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound,
|
||||||
|
std::make_shared<StrokePlain>(QColor(255,255,255),1,1))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
TestGLWidget w(style);
|
TestGLWidget w(style);
|
||||||
w.show();
|
w.show();
|
||||||
a.exec();
|
a.exec();
|
||||||
|
@ -38,13 +155,12 @@ namespace UnitTest
|
||||||
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
{
|
{
|
||||||
std::map<float, Material> materialMap = {
|
std::map<float, Material> materialMap = {
|
||||||
{0.25, Material{QColor(255,0,0)}},
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
{0.50, Material{QColor(0,255,0)}},
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
{0.75, Material{QColor(0,0,255)}},
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
{1.00, Material{QColor(255,255,0)}},
|
|
||||||
};
|
};
|
||||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
std::make_shared<MaterialStyleStroke>(4, StrokeType::kLeftSide, StrokeEndType::kRound,
|
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound,
|
||||||
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
}
|
}
|
||||||
} style;
|
} style;
|
||||||
|
@ -65,12 +181,12 @@ namespace UnitTest
|
||||||
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
{
|
{
|
||||||
std::map<float, Material> materialMap = {
|
std::map<float, Material> materialMap = {
|
||||||
{0.50, Material{QColor(0,255,0)}},
|
{0.00, Material{QColor(255,255,255)}},
|
||||||
{0.75, Material{QColor(0,0,255)}},
|
{0.50, Material{QColor(165,176,207)}},
|
||||||
{1.00, Material{QColor(255,255,0)}},
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
};
|
};
|
||||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
std::make_shared<MaterialStyleStroke>(30, StrokeType::kLeftSide, StrokeEndType::kRound,
|
std::make_shared<MaterialStyleStroke>(30, StrokeType::kBothSides, StrokeEndType::kRound,
|
||||||
std::make_shared<StrokeRadialGradient>(materialMap, true))) };
|
std::make_shared<StrokeRadialGradient>(materialMap, true))) };
|
||||||
}
|
}
|
||||||
} style;
|
} style;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include "Renderer/Preview/ElementRenderer.h"
|
#include "Renderer/Preview/ElementRenderer.h"
|
||||||
#include "Editor/ThirdPartyLib/qquick/qquicksvgparser_p.h"
|
#include "Editor/ThirdPartyLib/qquick/qquicksvgparser_p.h"
|
||||||
|
#include "Editor/util/PainterPathUtil.h"
|
||||||
#include "Renderer/Painting/MaterialStyleStroke.h"
|
#include "Renderer/Painting/MaterialStyleStroke.h"
|
||||||
#include "Renderer/Painting/ElementStyle.h"
|
#include "Renderer/Painting/ElementStyle.h"
|
||||||
|
|
||||||
|
@ -25,12 +26,13 @@ namespace UnitTest
|
||||||
};
|
};
|
||||||
void paintGL() override
|
void paintGL() override
|
||||||
{
|
{
|
||||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
glClearColor(219/255., 78/255., 32/255., 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", path);
|
QQuickSvgParser::parsePathDataFast("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15", path);
|
||||||
|
path = PainterPathUtil::monotonization(path);
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.scale(5, 5);
|
transform.scale(10, 10);
|
||||||
path = transform.map(path);
|
path = transform.map(path);
|
||||||
float pixelRatio = devicePixelRatioF();
|
float pixelRatio = devicePixelRatioF();
|
||||||
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false);
|
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false);
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\*.obj;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperCore\debug\FramelessHelperCore.lib;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperWidgets\debug\FramelessHelperWidgets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\*.obj;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperCore\debug\FramelessHelperCore.lib;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperWidgets\debug\FramelessHelperWidgets.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
|
Loading…
Reference in New Issue