提供变宽样式的接口,未实现

dev-wuyize
wuyize 2023-03-23 23:09:51 +08:00
parent a3d39b32e5
commit b2e49dae17
9 changed files with 149 additions and 88 deletions

View File

@ -72,6 +72,7 @@
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level1</WarningLevel> <WarningLevel>Level1</WarningLevel>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<TreatSpecificWarningsAsErrors>4715;</TreatSpecificWarningsAsErrors>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -557,7 +557,7 @@ int solve_quartic(vec4 coeffs, inout vec4 s)
return num; return num;
} }
float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd) float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd, out float t)
{ {
// switch points when near to end point to minimize numerical error // switch points when near to end point to minimize numerical error
@ -794,7 +794,13 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
{ {
roots[i] = clamp(roots[i], 0., 1.); roots[i] = clamp(roots[i], 0., 1.);
vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3); vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3);
d0 = min(d0, dot(to_curve, to_curve)); float d = dot(to_curve, to_curve);
if (d < d0)
{
d0 = d;
t = roots[i];
}
// d0 = min(d0, dot(to_curve, to_curve));
} }
else else
{ {
@ -893,11 +899,11 @@ bool angleLargeThanPi(vec2 a, vec2 b)
/************************************************************************************/ /************************************************************************************/
void drawLine(in float d, uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness) void drawLine(in float d, uint styleHeadIndex, 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[styleHeadIndex]);
vec4 head = unpackUnorm4x8(headUint); vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a * 100) % 10) switch (int(head.a * 100) % 10)
// switch (2) // switch (2)
@ -905,7 +911,7 @@ void drawLine(in float d, uint styleIndex, out vec4 elementColor, out vec2 metal
/// 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[styleHeadIndex + 1])).rgb, 1);
break; break;
} }
/// RadialGradient /// RadialGradient
@ -913,16 +919,16 @@ void drawLine(in float d, uint styleIndex, out vec4 elementColor, out vec2 metal
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[styleHeadIndex + 1 + 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[styleHeadIndex + 2 + 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[styleHeadIndex + 1 + 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[styleHeadIndex + 2 + i * 2])).rgb, 1);
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg; vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
if (d <= level) if (d <= level)
{ {
@ -969,21 +975,24 @@ void drawLine(in float d, uint styleIndex, out vec4 elementColor, out vec2 metal
} }
} }
/**
* @param styleIndex ÊäÈëstyleHeadµÄIndex£¬·µ»ØÏÂÒ»¸östyleµÄindex
*/
void nextStyleIndex(inout uint styleIndex) void nextStyleIndex(inout uint styleIndex)
{ {
uint headUint = floatBitsToUint(style[styleIndex + 1]); uint headUint = floatBitsToUint(style[styleIndex]);
vec4 head = unpackUnorm4x8(headUint); vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a * 100) % 10) switch (int(head.a * 100) % 10)
{ {
/// Plain /// Plain
case 0: { case 0: {
styleIndex += 3; styleIndex += 2;
break; break;
} }
/// RadialGradient /// RadialGradient
case 1: { case 1: {
uint size = headUint % (1 << 15); uint size = headUint % (1 << 15);
styleIndex += 2 + size * 2; styleIndex += 1 + size * 2;
break; break;
} }
case 2: { case 2: {
@ -998,9 +1007,9 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, ve
vec2 normal; vec2 normal;
if (onVeryBegin) if (onVeryBegin)
{ {
if (endType%2 == 0) if (endType % 2 == 0)
return true; return true;
else if (endType%2 == 1) else if (endType % 2 == 1)
normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin)); normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
} }
else else
@ -1017,9 +1026,9 @@ bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 t
vec2 normal; vec2 normal;
if (onVeryEnd) if (onVeryEnd)
{ {
if ((endType/2)%2 == 0) if ((endType / 2) % 2 == 0)
return true; return true;
else if ((endType/2)%2 == 1) else if ((endType / 2) % 2 == 1)
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd); normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
} }
else else
@ -1034,11 +1043,7 @@ bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 t
void main() void main()
{ {
uvec2 pixelLocation = gl_GlobalInvocationID.xy; uvec2 pixelLocation = gl_GlobalInvocationID.xy;
// imageStore(gBaseColor, ivec2(pixelLocation), vec4(vec2(pixelLocation)/vec2(imageSize(gBaseColor)), 1,1));
vec4 color = vec4(0); vec4 color = vec4(0);
// if(isinf(path[0].x)) imageStore(gBaseColor, ivec2(pixelLocation),
// vec4(vec2(pixelLocation)/vec2(imageSize(gBaseColor)), 1,1)); return;
for (uint styleIndex = 0; styleIndex < styleSize;) for (uint styleIndex = 0; styleIndex < styleSize;)
{ {
styleIndex += 6; styleIndex += 6;
@ -1063,7 +1068,7 @@ void main()
continue; continue;
} }
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]); mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
++pathIndex;
num_its += cubic_bezier_int_test(localUV, p[0], p[1], p[2], p[3]); num_its += cubic_bezier_int_test(localUV, p[0], p[1], p[2], p[3]);
p3Last = p[3]; p3Last = p[3];
p2Last = p[2]; p2Last = p[2];
@ -1075,22 +1080,23 @@ void main()
vec4 head = unpackUnorm4x8(floatBitsToUint(style[styleIndex])); vec4 head = unpackUnorm4x8(floatBitsToUint(style[styleIndex]));
if (head.z == 0) if (head.z == 0)
{ {
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+1])).rgb, 1); elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 1])).rgb, 1);
} }
} }
styleIndex += 2; styleIndex += 2;
} }
else // Stroke else // Stroke
{ {
uint widthMapSize = floatBitsToUint(style[styleIndex + 1]);
float minDistance = 1e38; float minDistance = 1e38;
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex + 1])); styleIndex += widthMapSize + 2;
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex]));
float lineType = floor(styleHead.b * 10); float lineType = floor(styleHead.b * 10);
int endType = int(round(styleHead.b * 100)) % 10; int endType = int(round(styleHead.b * 100)) % 10;
int debugBegin = 0; int debugBegin = 0;
bool onVeryBegin = false; bool onVeryBegin = false;
bool onVeryEnd = false; bool onVeryEnd = false;
vec2 tangentEndLast; vec2 tangentEndLast = vec2(0);
vec2 tangentFirstBegin; vec2 tangentFirstBegin;
uint lastHitIndex = 0; uint lastHitIndex = 0;
bool lastHitElement = false; bool lastHitElement = false;
@ -1103,12 +1109,12 @@ void main()
pBegin = path[++pathIndex]; pBegin = path[++pathIndex];
p3Last = pBegin; p3Last = pBegin;
p2Last = pBegin; p2Last = pBegin;
if(endType == 4 /*StrokeEndType::kClosed*/) if (endType == 4 /*StrokeEndType::kClosed*/)
{ {
//onVeryBegin = false; // onVeryBegin = false;
vec2 lastP1 = path[pathSize-3]; vec2 lastP1 = path[pathSize - 4];
vec2 lastP2 = path[pathSize-2]; vec2 lastP2 = path[pathSize - 3];
vec2 lastP3 = path[pathSize-1]; vec2 lastP3 = path[pathSize - 2];
if (lastP3 != lastP2) if (lastP3 != lastP2)
tangentEndLast = normalize(lastP3 - lastP2); tangentEndLast = normalize(lastP3 - lastP2);
else else
@ -1119,13 +1125,13 @@ void main()
continue; continue;
} }
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]); mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
vec2 lengthRate = path[++pathIndex];
vec2 tangentBeginNext; vec2 tangentBeginNext;
if (pathIndex + 1 < pathSize) if (pathIndex + 1 < pathSize)
{ {
vec2 pTemp = path[pathIndex + 1]; vec2 pTemp = path[pathIndex + 1];
if (isinf(pTemp.x)) if (isinf(pTemp.x))
{ {
onVeryEnd = true; onVeryEnd = true;
} }
else else
@ -1140,31 +1146,35 @@ void main()
} }
else else
{ {
if(endType == 4 /*StrokeEndType::kClosed*/) if (endType == 4 /*StrokeEndType::kClosed*/)
{ {
//onVeryEnd = false; // onVeryEnd = false;
tangentBeginNext = tangentFirstBegin; tangentBeginNext = tangentFirstBegin;
} }
else else
onVeryEnd = true; onVeryEnd = true;
} }
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true); vec2 tangentEnd;
if (d <= strokeWidth) if (p[3] != p[2])
tangentEnd = normalize(p[3] - p[2]);
else
tangentEnd = normalize(p[3] - p[1]);
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);
if (d <= localWidth)
{ {
bool onBegin = distance(localUV, p[0]) <= strokeWidth; bool onBegin = t<1e-5;
bool onEnd = distance(localUV, p[3]) <= strokeWidth; bool onEnd = t>1-1e-5;
//bool onBegin = true;
//bool onEnd = true;
vec2 tangentBegin; vec2 tangentBegin;
vec2 tangentEnd;
if (p[0] != p[1]) if (p[0] != p[1])
tangentBegin = normalize(p[0] - p[1]); tangentBegin = normalize(p[0] - p[1]);
else else
tangentBegin = normalize(p[0] - p[2]); tangentBegin = normalize(p[0] - p[2]);
if (p[3] != p[2])
tangentEnd = normalize(p[3] - p[2]);
else
tangentEnd = normalize(p[3] - p[1]);
bool hit = d < minDistance; bool hit = d < minDistance;
if (onBegin) if (onBegin)
@ -1192,19 +1202,19 @@ void main()
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 / localWidth, styleIndex, elementColor, metallicRoughness);
} }
} }
tangentEndLast = tangentEnd; if (pathIndex == 5)
if(pathIndex == 4)
tangentFirstBegin = tangentBegin; tangentFirstBegin = tangentBegin;
} }
tangentEndLast = tangentEnd;
p3Last = p[3]; p3Last = p[3];
p2Last = p[2]; p2Last = p[2];
onVeryBegin = false; onVeryBegin = false;
} }
nextStyleIndex(styleIndex); nextStyleIndex(styleIndex);
} }
if (hitElement) if (hitElement)
color = elementColor; color = elementColor;

View File

@ -959,11 +959,11 @@ bool angleLargeThanPi(vec2 a, vec2 b)
return a.x * b.y - b.x * a.y < 0; return a.x * b.y - b.x * a.y < 0;
} }
void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness) void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness)
{ {
elementColor = vec4(1); elementColor = vec4(1);
metallicRoughness = vec2(0.8); metallicRoughness = vec2(0.8);
uint headUint = floatBitsToUint(elementData[styleIndex + 1]); uint headUint = floatBitsToUint(elementData[styleHeadIndex]);
vec4 head = unpackUnorm4x8(headUint); vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a * 100) % 10) switch (int(head.a * 100) % 10)
// switch (2) // switch (2)
@ -971,7 +971,7 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
/// Plain /// Plain
case 0: { case 0: {
metallicRoughness = head.rg; metallicRoughness = head.rg;
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 2])).rgb, 1); elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleHeadIndex + 1])).rgb, 1);
break; break;
} }
/// RadialGradient /// RadialGradient
@ -979,16 +979,16 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
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(elementData[styleIndex + 2 + 0 * 2]); uint lastData = floatBitsToUint(elementData[styleHeadIndex + 1 + 0 * 2]);
float lastLevel = 0; float lastLevel = 0;
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg; vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 3 + 0 * 2])).rgb, 1); vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleHeadIndex + 2 + 0 * 2])).rgb, 1);
for (uint i = 0; i < size; i++) for (uint i = 0; i < size; i++)
{ {
uint data = floatBitsToUint(elementData[styleIndex + 2 + i * 2]); uint data = floatBitsToUint(elementData[styleHeadIndex + 1 + i * 2]);
float level = unpackUnorm2x16(data).y; float level = unpackUnorm2x16(data).y;
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 3 + i * 2])).rgb, 1); vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleHeadIndex + 2 + i * 2])).rgb, 1);
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg; vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
if (d <= level) if (d <= level)
{ {
@ -1152,7 +1152,9 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
float minDistance = 1e38; float minDistance = 1e38;
uint lineCount = elementIndexs[contourIndex]; uint lineCount = elementIndexs[contourIndex];
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1])); uint widthMapSize = floatBitsToUint(elementData[styleIndex + 1]);
styleIndex += widthMapSize + 2;
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex]));
float lineType = floor(styleHead.b * 10); float lineType = floor(styleHead.b * 10);
int endType = int(round(styleHead.b * 100)) % 10; int endType = int(round(styleHead.b * 100)) % 10;
vec2 p3Last = vec2(1e38); vec2 p3Last = vec2(1e38);

View File

@ -413,6 +413,8 @@ int CubicBezierSignedDistance::solve_quadric(dvec2 coeffs, dvec2& roots) {
return 2; return 2;
} }
else
return 0;
} }
void CubicBezierSignedDistance::sort_roots3(dvec3& roots) { void CubicBezierSignedDistance::sort_roots3(dvec3& roots) {

View File

@ -77,8 +77,8 @@ bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
&& materialMap == static_cast<const StrokeRadialGradient&>(m).materialMap; && materialMap == static_cast<const StrokeRadialGradient&>(m).materialMap;
} }
Renderer::MaterialStyleStroke::MaterialStyleStroke(float halfWidth, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke) Renderer::MaterialStyleStroke::MaterialStyleStroke(float halfWidth, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke, std::map<float, float> widthMap)
: halfWidth(halfWidth), strokeType(strokeType), endType(endType), materialStroke(materialStroke) : halfWidth(halfWidth), strokeType(strokeType), endType(endType), materialStroke(materialStroke), widthMap(widthMap)
{ {
} }
@ -89,7 +89,9 @@ MaterialStyleType Renderer::MaterialStyleStroke::type() const
std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
{ {
std::vector<GLfloat> v = { halfWidth }; std::vector<GLfloat> v = { halfWidth, glm::uintBitsToFloat(widthMap.size()) };
for(auto& [lengthRate, widthRate] : widthMap)
v.emplace_back(glm::uintBitsToFloat(glm::packUnorm2x16(glm::vec2(lengthRate, widthRate))));
auto encoded = materialStroke->encoded(); auto encoded = materialStroke->encoded();
glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0])); glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0]));
head.b = (float)strokeType / 10. + (float)endType / 100.; head.b = (float)strokeType / 10. + (float)endType / 100.;

View File

@ -48,7 +48,7 @@ namespace Renderer
class MaterialStyleStroke : public MaterialStyle class MaterialStyleStroke : public MaterialStyle
{ {
public: public:
MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke); MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke, std::map<float, float> widthMap = {});
virtual MaterialStyleType type() const override; virtual MaterialStyleType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialStyle> clone() const override; virtual std::unique_ptr<MaterialStyle> clone() const override;
@ -59,6 +59,7 @@ namespace Renderer
StrokeType strokeType; StrokeType strokeType;
StrokeEndType endType; StrokeEndType endType;
std::shared_ptr<MaterialStroke> materialStroke; std::shared_ptr<MaterialStroke> materialStroke;
std::map<float, float> widthMap;
static const std::array<std::pair<QString, StrokeEndType>, 4> strokeEndTypeNames; static const std::array<std::pair<QString, StrokeEndType>, 4> strokeEndTypeNames;
}; };
} }

View File

@ -15,6 +15,8 @@ using namespace Renderer;
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path) std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
{ {
float lastLength = 0;
glm::vec2 lastPoint;
std::vector<glm::vec2> pathBuffer; std::vector<glm::vec2> pathBuffer;
for (int i = 0; i < path.elementCount(); i++) for (int i = 0; i < path.elementCount(); i++)
{ {
@ -24,18 +26,24 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
case QPainterPath::MoveToElement: case QPainterPath::MoveToElement:
//qDebug() << "MoveToElement"; //qDebug() << "MoveToElement";
//qDebug() << element; //qDebug() << element;
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity())); pathBuffer.emplace_back(std::numeric_limits<float>::infinity());
pathBuffer.push_back(glm::vec2(element.x, element.y)); pathBuffer.emplace_back(element.x, element.y);
lastLength = 0;
lastPoint = glm::vec2(element.x, element.y);
break; break;
case QPainterPath::LineToElement: case QPainterPath::LineToElement:
{ {
//qDebug() << "LineToElement"; //qDebug() << "LineToElement";
//qDebug() << element; //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 = (lastPoint + end) / 2.f;
pathBuffer.push_back(mid); pathBuffer.push_back(mid);
pathBuffer.push_back(mid); pathBuffer.push_back(mid);
pathBuffer.push_back(end); pathBuffer.push_back(end);
float length = (i + 1.) / path.elementCount();
pathBuffer.emplace_back(lastLength, length);
lastLength = length;
lastPoint = end;
break; break;
} }
case QPainterPath::CurveToElement: case QPainterPath::CurveToElement:
@ -49,16 +57,20 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
element = path.elementAt(++i); element = path.elementAt(++i);
//qDebug() << element; //qDebug() << element;
glm::vec2 p3 = glm::vec2(element.x, element.y); glm::vec2 p3 = glm::vec2(element.x, element.y);
if (p3 != pathBuffer.back()) if (p3 != lastPoint)
{ {
pathBuffer.push_back(p1); pathBuffer.push_back(p1);
pathBuffer.push_back(p2); pathBuffer.push_back(p2);
pathBuffer.push_back(p3); pathBuffer.push_back(p3);
float length = (i + 1.) / path.elementCount();
pathBuffer.emplace_back(lastLength, length);
lastLength = length;
lastPoint = p3;
} }
break; break;
} }
case QPainterPath::CurveToDataElement: case QPainterPath::CurveToDataElement:
pathBuffer.push_back(glm::vec2(element.x, element.y)); qCritical() << "Read QPainterPath Error";
break; break;
} }
} }

View File

@ -206,9 +206,9 @@ namespace UnitTest
} }
TEST_METHOD(TestBothSidesClosed) TEST_METHOD(TestBothSidesClosed)
{ {
QPainterPath closedPath; QPainterPath testPath;
SvgFileLoader().loadSvgFile("../../svg/4_L0.svg", closedPath); SvgFileLoader().loadSvgFile("../../svg/4_L0.svg", testPath);
closedPath = QTransform::fromScale(5, 5).map(closedPath); testPath = QTransform::fromScale(5, 5).map(testPath);
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -220,11 +220,60 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(20, StrokeType::kLeftSide, StrokeEndType::kClosed, std::make_shared<MaterialStyleStroke>(10, StrokeType::kBothSides, StrokeEndType::kClosed,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
TestGLWidget w(style, closedPath); TestGLWidget w(style, testPath);
w.show();
a.exec();
}
TEST_METHOD(TestAcuteAngle)
{
QPainterPath testPath;
testPath.moveTo(50, 50);
testPath.lineTo(300, 300);
testPath.lineTo(300, 50);
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>(20, StrokeType::kRightSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;
TestGLWidget w(style, testPath);
w.show();
a.exec();
}
TEST_METHOD(TestBothSidesGradientWidth)
{
QPainterPath testPath;
testPath.moveTo(50, 50);
testPath.cubicTo(50, 200, 200, 300, 300, 300);
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>(20, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;
TestGLWidget w(style, testPath);
w.show(); w.show();
a.exec(); a.exec();
} }

View File

@ -343,24 +343,6 @@
</QtMoc> </QtMoc>
<ClInclude Include="qtmaterialtoggle_p.h" /> <ClInclude Include="qtmaterialtoggle_p.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2&gt;NUL &gt;debug\moc_predefs.h</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_predefs.h;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Include="release\moc_predefs.h.cbt">
<FileType>Document</FileType>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2&gt;NUL &gt;release\moc_predefs.h</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\fonts\Roboto\Roboto-Black.ttf" /> <None Include="..\fonts\Roboto\Roboto-Black.ttf" />
<None Include="..\fonts\Roboto\Roboto-Bold.ttf" /> <None Include="..\fonts\Roboto\Roboto-Bold.ttf" />