初步实现变宽样式
parent
edb529e7da
commit
5ac322fb30
|
@ -899,6 +899,36 @@ bool angleLargeThanPi(vec2 a, vec2 b)
|
|||
|
||||
/************************************************************************************/
|
||||
|
||||
float getLocalWidth(float t, vec2 lengthRate, float originWidth, uint widthMapSize, uint widthMapIndex)
|
||||
{
|
||||
if(widthMapSize == 0)
|
||||
return originWidth;
|
||||
float width;
|
||||
vec2 lastData = unpackUnorm2x16(floatBitsToUint(style[widthMapIndex]));
|
||||
float lastLevel = 0;
|
||||
float lastWidth = lastData.y;
|
||||
float currentLengthRate = mix(lengthRate.x, lengthRate.y, t);
|
||||
bool found = false;
|
||||
for (uint i = 0; i < widthMapSize; i++)
|
||||
{
|
||||
vec2 data = unpackUnorm2x16(floatBitsToUint(style[widthMapIndex + i]));
|
||||
float level = data.x;
|
||||
float currentWidth = data.y;
|
||||
if (currentLengthRate <= level)
|
||||
{
|
||||
float a = (currentLengthRate - lastLevel) / (level - lastLevel);
|
||||
width = mix(lastWidth, currentWidth, a);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
lastWidth = currentWidth;
|
||||
lastLevel = level;
|
||||
}
|
||||
if(!found)
|
||||
width = lastWidth;
|
||||
return width * originWidth;
|
||||
}
|
||||
|
||||
void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
||||
{
|
||||
elementColor = vec4(1);
|
||||
|
@ -1100,6 +1130,7 @@ void main()
|
|||
else // Stroke
|
||||
{
|
||||
uint widthMapSize = floatBitsToUint(style[styleIndex + 1]);
|
||||
uint widthMapIndex = styleIndex + 2;
|
||||
float minDistance = 1e38;
|
||||
styleIndex += widthMapSize + 2;
|
||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex]));
|
||||
|
@ -1177,7 +1208,7 @@ void main()
|
|||
|
||||
float t;
|
||||
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true, t);
|
||||
float localWidth = strokeWidth; // * mix(lengthRate.x, lengthRate.y, t);
|
||||
float localWidth = getLocalWidth(t, lengthRate, strokeWidth, widthMapSize, widthMapIndex);
|
||||
if (d <= localWidth)
|
||||
{
|
||||
bool hit = d < minDistance;
|
||||
|
|
|
@ -10,15 +10,55 @@
|
|||
#include "../Painting/Element.h"
|
||||
#include "../Painting/Painting.h"
|
||||
#include "../Painting/MaterialStyleStroke.h"
|
||||
#include "../Painting/CubicBezier.h"
|
||||
#include <util/PainterPathUtil.h>
|
||||
using namespace Renderer;
|
||||
|
||||
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||
{
|
||||
float lastLength = 0;
|
||||
glm::vec2 lastPoint;
|
||||
std::vector<glm::vec2> pathBuffer;
|
||||
std::vector<std::vector<float>> lengths;
|
||||
for (int i = 0; i < path.elementCount(); i++)
|
||||
{
|
||||
QPainterPath::Element element = path.elementAt(i);
|
||||
switch (element.type)
|
||||
{
|
||||
case QPainterPath::MoveToElement:
|
||||
{
|
||||
lastPoint = glm::vec2(element.x, element.y);
|
||||
lengths.push_back({ 0 });
|
||||
break;
|
||||
}
|
||||
case QPainterPath::LineToElement:
|
||||
{
|
||||
glm::vec2 end = glm::vec2(element.x, element.y);
|
||||
float length = glm::distance(lastPoint, end);
|
||||
lengths.back().push_back(lengths.back().back() + length);
|
||||
break;
|
||||
}
|
||||
case QPainterPath::CurveToElement:
|
||||
{
|
||||
Point p1(element.x, element.y);
|
||||
element = path.elementAt(++i);
|
||||
Point p2(element.x, element.y);
|
||||
element = path.elementAt(++i);
|
||||
Point p3(element.x, element.y);
|
||||
if (glm::vec2(p3.x, p3.y) != lastPoint)
|
||||
{
|
||||
float length = CubicBezier(std::vector{ Point(lastPoint.x, lastPoint.y), p1, p2, p3 }).getIntegralByT(1);
|
||||
lengths.back().push_back(lengths.back().back() + length);
|
||||
lastPoint = glm::vec2(p3.x, p3.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QPainterPath::CurveToDataElement:
|
||||
qCritical() << "Read QPainterPath Error";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<glm::vec2> pathBuffer;
|
||||
for (int i = 0, j = -1, k = 0; i < path.elementCount(); i++)
|
||||
{
|
||||
QPainterPath::Element element = path.elementAt(i);
|
||||
switch (element.type)
|
||||
|
@ -28,8 +68,8 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
|||
//qDebug() << element;
|
||||
pathBuffer.emplace_back(std::numeric_limits<float>::infinity());
|
||||
pathBuffer.emplace_back(element.x, element.y);
|
||||
lastLength = 0;
|
||||
lastPoint = glm::vec2(element.x, element.y);
|
||||
j++;
|
||||
break;
|
||||
case QPainterPath::LineToElement:
|
||||
{
|
||||
|
@ -40,9 +80,9 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
|||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(end);
|
||||
float length = (i + 1.) / path.elementCount();
|
||||
pathBuffer.emplace_back(lastLength, length);
|
||||
lastLength = length;
|
||||
pathBuffer.emplace_back(lengths[j][k] / lengths[j].back(), lengths[j][k+1] / lengths[j].back());
|
||||
k++;
|
||||
qDebug() << pathBuffer.back().x << pathBuffer.back().y;
|
||||
lastPoint = end;
|
||||
break;
|
||||
}
|
||||
|
@ -62,9 +102,9 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
|||
pathBuffer.push_back(p1);
|
||||
pathBuffer.push_back(p2);
|
||||
pathBuffer.push_back(p3);
|
||||
float length = (i + 1.) / path.elementCount();
|
||||
pathBuffer.emplace_back(lastLength, length);
|
||||
lastLength = length;
|
||||
pathBuffer.emplace_back(lengths[j][k] / lengths[j].back(), lengths[j][k+1] / lengths[j].back());
|
||||
k++;
|
||||
qDebug() << pathBuffer.back().x << pathBuffer.back().y;
|
||||
lastPoint = p3;
|
||||
}
|
||||
break;
|
||||
|
@ -145,7 +185,7 @@ Renderer::ElementRenderer::ElementRenderer()
|
|||
thread = std::jthread([&](std::stop_token stop) {
|
||||
std::stop_callback cb(stop, [&] {
|
||||
draw.notify_all();
|
||||
});
|
||||
});
|
||||
|
||||
QOpenGLContext context;
|
||||
context.create();
|
||||
|
@ -205,7 +245,7 @@ Renderer::ElementRenderer::ElementRenderer()
|
|||
draw.notify_all();
|
||||
}
|
||||
context.doneCurrent();
|
||||
});
|
||||
});
|
||||
|
||||
while (!initialized)
|
||||
std::this_thread::yield();
|
||||
|
|
|
@ -255,9 +255,12 @@ namespace UnitTest
|
|||
}
|
||||
TEST_METHOD(TestBothSidesGradientWidth)
|
||||
{
|
||||
QPainterPath testPath;
|
||||
/*QPainterPath testPath;
|
||||
testPath.moveTo(50, 50);
|
||||
testPath.cubicTo(50, 200, 200, 300, 300, 300);
|
||||
testPath.cubicTo(50, 200, 200, 300, 300, 300);*/
|
||||
QPainterPath testPath;
|
||||
SvgFileLoader().loadSvgFile("../../svg/3.svg", testPath);
|
||||
testPath = QTransform::fromScale(10, 10).map(testPath);
|
||||
QApplication a(argc, argv);
|
||||
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||
{
|
||||
|
@ -269,8 +272,8 @@ namespace UnitTest
|
|||
{1.00, Material{QColor(58,64,151)}}
|
||||
};
|
||||
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||
std::make_shared<MaterialStyleStroke>(20, StrokeType::kLeftSide, StrokeEndType::kRound,
|
||||
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||
std::make_shared<MaterialStyleStroke>(80, StrokeType::kRightSide, StrokeEndType::kFlatRound,
|
||||
std::make_shared<StrokeRadialGradient>(materialMap, false), std::map<float, float>{ {0,1},{1,0}})) };
|
||||
}
|
||||
} style;
|
||||
TestGLWidget w(style, testPath);
|
||||
|
|
Loading…
Reference in New Issue