Added ability to draw solid strokes with dashes

[issues 1479: Shape](https://github.com/thorvg/thorvg/issues/1479)

In order to build you need third party libraries. Before you start please read this: [LearnWebGPU](https://eliemichel.github.io/LearnWebGPU/getting-started/hello-webgpu.html)

Usage example:

    // init glfw
    glfwInit();

    // create a windowed mode window and its opengl context
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    GLFWwindow* window = glfwCreateWindow(800, 800, "WebGPU base app", nullptr, nullptr);

    // get window size
    int width{}, height{};
    glfwGetWindowSize(window, &width, &height);

    // init engine webgpu
    tvg::Initializer::init(tvg::CanvasEngine::Wg, 0);

    // create wg canvas
    auto canvasWg = tvg::WgCanvas::gen();
    canvas_wg->target(glfwGetWin32Window(window), width, height);

    //Test for Stroke Dash for Arc, Circle, Rect
    auto shape = tvg::Shape::gen();
    shape->appendArc(70, 600, 160, 10, 30, true);
    shape->appendCircle(70, 700, 20, 60);
    shape->appendRect(130, 710, 100, 40);
    shape->strokeFill(255, 0, 0);
    shape->strokeWidth(5);
    shape->strokeJoin(tvg::StrokeJoin::Round);
    shape->strokeCap(tvg::StrokeCap::Round);
    float dashPattern[2] = {20, 10};
    shape->strokeDash(dashPattern, 2);
    if (canvas_wg->push(std::move(shape)) != tvg::Result::Success) return;

    while (!glfwWindowShouldClose(window)) {
        // webgpu
        canvas_wg->draw();
        canvas_wg->sync();

        // pull events
        glfwPollEvents();
    }

    // terminate engine and window
    tvg::Initializer::term(tvg::CanvasEngine::Wg);
    glfwDestroyWindow(window);
    glfwTerminate();
This commit is contained in:
Sergii Liebodkin 2023-11-01 12:06:21 +02:00 committed by Hermet Park
parent a3adbef2c2
commit 52eca9630c
2 changed files with 46 additions and 1 deletions

View file

@ -184,6 +184,13 @@ void WgRenderDataShape::stroke(WGPUDevice device, WGPUQueue queue, const RenderS
decodePath(rshape, outlines);
WgVertexList strokes;
if (rshape.stroke->dashPattern) {
Array<WgVertexList*> segments;
strokeSegments(rshape, outlines, segments);
strokeSublines(rshape, segments, strokes);
for (uint32_t i = 0; i < segments.count; i++)
delete segments[i];
} else
strokeSublines(rshape, outlines, strokes);
// append shape if it can create at least one triangle
@ -230,6 +237,43 @@ void WgRenderDataShape::decodePath(const RenderShape& rshape, Array<WgVertexList
}
}
void WgRenderDataShape::strokeSegments(const RenderShape& rshape, Array<WgVertexList*>& outlines, Array<WgVertexList*>& segments) {
for (uint32_t i = 0; i < outlines.count; i++) {
auto& vlist = outlines[i]->mVertexList;
// append single point segment
if (vlist.count == 1) {
auto segment = new WgVertexList();
segment->mVertexList.push(vlist.last());
segments.push(segment);
}
if (vlist.count >= 2) {
uint32_t icurr = 1;
uint32_t ipatt = 0;
WgPoint vcurr = vlist[0];
while (icurr < vlist.count) {
if (ipatt % 2 == 0) {
segments.push(new WgVertexList());
segments.last()->mVertexList.push(vcurr);
}
float lcurr = rshape.stroke->dashPattern[ipatt];
while ((icurr < vlist.count) && (vlist[icurr].dist(vcurr) < lcurr)) {
lcurr -= vlist[icurr].dist(vcurr);
vcurr = vlist[icurr];
icurr++;
if (ipatt % 2 == 0) segments.last()->mVertexList.push(vcurr);
}
if (icurr < vlist.count) {
vcurr = vcurr + (vlist[icurr] - vlist[icurr-1]).normal() * lcurr;
if (ipatt % 2 == 0) segments.last()->mVertexList.push(vcurr);
}
ipatt = (ipatt + 1) % rshape.stroke->dashCnt;
}
}
}
}
void WgRenderDataShape::strokeSublines(const RenderShape& rshape, Array<WgVertexList*>& outlines, WgVertexList& strokes) {
float wdt = rshape.stroke->width / 2;
for (uint32_t i = 0; i < outlines.count; i++) {

View file

@ -83,6 +83,7 @@ public:
void stroke(WGPUDevice device, WGPUQueue queue, const RenderShape& rshape);
private:
void decodePath(const RenderShape& rshape, Array<WgVertexList*>& outlines);
void strokeSegments(const RenderShape& rshape, Array<WgVertexList*>& outlines, Array<WgVertexList*>& segments);
void strokeSublines(const RenderShape& rshape, Array<WgVertexList*>& outlines, WgVertexList& strokes);
};