mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
wg_engine: stroke trim
[issues 1479: strokes](#1479) Introduced stroke trim setting left: (0, 0.95) middle: (0.15, 1) right: (0.15, 0.95)
This commit is contained in:
parent
2f196b514f
commit
98b30c72ef
2 changed files with 120 additions and 60 deletions
|
@ -204,6 +204,40 @@ void WgGeometryData::appendMesh(const RenderMesh* rmesh)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
WgPoint WgGeometryData::interpolate(float t, uint32_t& index)
|
||||||
|
{
|
||||||
|
assert(t >= 0.0f);
|
||||||
|
assert(t <= 1.0f);
|
||||||
|
// get total length
|
||||||
|
float totalLength = 0.0f;
|
||||||
|
for (uint32_t i = 0; i < positions.count - 1; i++)
|
||||||
|
totalLength += positions[i].dist(positions[i+1]);
|
||||||
|
float targetLength = totalLength * t;
|
||||||
|
// find current segment index and interpolation factor
|
||||||
|
float currentFactor = 0.0f;
|
||||||
|
float currentLength = 0.0f;
|
||||||
|
for (index = 0; index < positions.count - 1; index++) {
|
||||||
|
float segmentLength = positions[index].dist(positions[index+1]);
|
||||||
|
currentLength += segmentLength;
|
||||||
|
if(currentLength >= targetLength) {
|
||||||
|
currentFactor = 1.0f -(currentLength - targetLength) / segmentLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get interpolated position and segment index
|
||||||
|
return positions[index] * (1.0f - currentFactor) + positions[index + 1] * currentFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float WgGeometryData::getLength()
|
||||||
|
{
|
||||||
|
float length = 0.0f;
|
||||||
|
for (uint32_t i = 0; i < positions.count - 1; i++)
|
||||||
|
length += positions[i].dist(positions[i+1]);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WgGeometryData::getClosestIntersection(WgPoint p1, WgPoint p2, WgPoint& pi, uint32_t& index)
|
bool WgGeometryData::getClosestIntersection(WgPoint p1, WgPoint p2, WgPoint& pi, uint32_t& index)
|
||||||
{
|
{
|
||||||
bool finded = false;
|
bool finded = false;
|
||||||
|
@ -327,28 +361,32 @@ void WgGeometryDataGroup::tesselate(const RenderShape& rshape)
|
||||||
void WgGeometryDataGroup::stroke(const RenderShape& rshape)
|
void WgGeometryDataGroup::stroke(const RenderShape& rshape)
|
||||||
{
|
{
|
||||||
assert(rshape.stroke);
|
assert(rshape.stroke);
|
||||||
|
auto strokeData = new WgGeometryData();
|
||||||
|
// decode
|
||||||
|
WgGeometryDataGroup polylines{};
|
||||||
|
decodePath(rshape, &polylines);
|
||||||
|
// trim -> split -> stroke
|
||||||
|
if ((rshape.stroke->dashPattern) && ((rshape.stroke->trim.begin != 0.0f) || (rshape.stroke->trim.end != 1.0f))) {
|
||||||
|
WgGeometryDataGroup trimmed{};
|
||||||
|
WgGeometryDataGroup splitted{};
|
||||||
|
trimPolyline(&polylines, &trimmed, rshape.stroke);
|
||||||
|
splitPolyline(&trimmed, &splitted, rshape.stroke);
|
||||||
|
strokePolyline(&splitted, strokeData, rshape.stroke);
|
||||||
|
} else // trim -> stroke
|
||||||
|
if ((rshape.stroke->trim.begin != 0.0f) || (rshape.stroke->trim.end != 1.0f)) {
|
||||||
|
WgGeometryDataGroup trimmed{};
|
||||||
|
trimPolyline(&polylines, &trimmed, rshape.stroke);
|
||||||
|
strokePolyline(&trimmed, strokeData, rshape.stroke);
|
||||||
|
} else // split -> stroke
|
||||||
if (rshape.stroke->dashPattern) {
|
if (rshape.stroke->dashPattern) {
|
||||||
// first step: decode path data
|
WgGeometryDataGroup splitted{};
|
||||||
WgGeometryDataGroup segments{};
|
splitPolyline(&polylines, &splitted, rshape.stroke);
|
||||||
decodePath(rshape, &segments);
|
strokePolyline(&splitted, strokeData, rshape.stroke);
|
||||||
// second step: split path to segments using dash patterns
|
} else { // stroke
|
||||||
WgGeometryDataGroup outlines{};
|
strokePolyline(&polylines, strokeData, rshape.stroke);
|
||||||
strokeSegments(rshape, &segments, &outlines);
|
|
||||||
// third step: create geometry for strokes
|
|
||||||
auto strokeData = new WgGeometryData;
|
|
||||||
strokeSublines(rshape, &outlines, strokeData);
|
|
||||||
// append strokes geometry data
|
|
||||||
geometries.push(strokeData);
|
|
||||||
} else {
|
|
||||||
// first step: decode path data
|
|
||||||
WgGeometryDataGroup outlines{};
|
|
||||||
decodePath(rshape, &outlines);
|
|
||||||
// second step: create geometry for strokes
|
|
||||||
auto strokeData = new WgGeometryData;
|
|
||||||
strokeSublines(rshape, &outlines, strokeData);
|
|
||||||
// append strokes geometry data
|
|
||||||
geometries.push(strokeData);
|
|
||||||
}
|
}
|
||||||
|
// append stroke geometry
|
||||||
|
geometries.push(strokeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,7 +400,6 @@ void WgGeometryDataGroup::contours(WgGeometryDataGroup& outlines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgGeometryDataGroup::release()
|
void WgGeometryDataGroup::release()
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < geometries.count; i++)
|
for (uint32_t i = 0; i < geometries.count; i++)
|
||||||
|
@ -371,27 +408,27 @@ void WgGeometryDataGroup::release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgGeometryDataGroup::decodePath(const RenderShape& rshape, WgGeometryDataGroup* outlines)
|
void WgGeometryDataGroup::decodePath(const RenderShape& rshape, WgGeometryDataGroup* polyline)
|
||||||
{
|
{
|
||||||
size_t pntIndex = 0;
|
size_t pntIndex = 0;
|
||||||
for (uint32_t cmdIndex = 0; cmdIndex < rshape.path.cmds.count; cmdIndex++) {
|
for (uint32_t cmdIndex = 0; cmdIndex < rshape.path.cmds.count; cmdIndex++) {
|
||||||
PathCommand cmd = rshape.path.cmds[cmdIndex];
|
PathCommand cmd = rshape.path.cmds[cmdIndex];
|
||||||
if (cmd == PathCommand::MoveTo) {
|
if (cmd == PathCommand::MoveTo) {
|
||||||
outlines->geometries.push(new WgGeometryData);
|
polyline->geometries.push(new WgGeometryData);
|
||||||
auto outline = outlines->geometries.last();
|
auto outline = polyline->geometries.last();
|
||||||
outline->positions.push(rshape.path.pts[pntIndex]);
|
outline->positions.push(rshape.path.pts[pntIndex]);
|
||||||
pntIndex++;
|
pntIndex++;
|
||||||
} else if (cmd == PathCommand::LineTo) {
|
} else if (cmd == PathCommand::LineTo) {
|
||||||
auto outline = outlines->geometries.last();
|
auto outline = polyline->geometries.last();
|
||||||
if (outline)
|
if (outline)
|
||||||
outline->positions.push(rshape.path.pts[pntIndex]);
|
outline->positions.push(rshape.path.pts[pntIndex]);
|
||||||
pntIndex++;
|
pntIndex++;
|
||||||
} else if (cmd == PathCommand::Close) {
|
} else if (cmd == PathCommand::Close) {
|
||||||
auto outline = outlines->geometries.last();
|
auto outline = polyline->geometries.last();
|
||||||
if ((outline) && (outline->positions.count > 0))
|
if ((outline) && (outline->positions.count > 0))
|
||||||
outline->positions.push(outline->positions[0]);
|
outline->positions.push(outline->positions[0]);
|
||||||
} else if (cmd == PathCommand::CubicTo) {
|
} else if (cmd == PathCommand::CubicTo) {
|
||||||
auto outline = outlines->geometries.last();
|
auto outline = polyline->geometries.last();
|
||||||
if ((outline) && (outline->positions.count > 0))
|
if ((outline) && (outline->positions.count > 0))
|
||||||
outline->appendCubic(
|
outline->appendCubic(
|
||||||
rshape.path.pts[pntIndex + 0],
|
rshape.path.pts[pntIndex + 0],
|
||||||
|
@ -404,16 +441,35 @@ void WgGeometryDataGroup::decodePath(const RenderShape& rshape, WgGeometryDataGr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgGeometryDataGroup::strokeSegments(const RenderShape& rshape, WgGeometryDataGroup* outlines, WgGeometryDataGroup* segments)
|
void WgGeometryDataGroup::trimPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* trimmed, RenderStroke *stroke)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < outlines->geometries.count; i++) {
|
assert(stroke);
|
||||||
auto& vlist = outlines->geometries[i]->positions;
|
for (uint32_t i = 0; i < polyline->geometries.count; i++) {
|
||||||
|
auto segment = new WgGeometryData;
|
||||||
|
uint32_t is = 0;
|
||||||
|
uint32_t ie = 0;
|
||||||
|
WgPoint vs = polyline->geometries[i]->interpolate(stroke->trim.begin, is);
|
||||||
|
WgPoint ve = polyline->geometries[i]->interpolate(stroke->trim.end, ie);
|
||||||
|
segment->positions.push(vs);
|
||||||
|
for (uint32_t j = is+1; j <= ie; j++)
|
||||||
|
segment->positions.push(polyline->geometries[i]->positions[j]);
|
||||||
|
segment->positions.push(ve);
|
||||||
|
trimmed->geometries.push(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgGeometryDataGroup::splitPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* splitted, RenderStroke *stroke)
|
||||||
|
{
|
||||||
|
assert(stroke);
|
||||||
|
for (uint32_t i = 0; i < polyline->geometries.count; i++) {
|
||||||
|
auto& vlist = polyline->geometries[i]->positions;
|
||||||
|
|
||||||
// append single point segment
|
// append single point segment
|
||||||
if (vlist.count == 1) {
|
if (vlist.count == 1) {
|
||||||
auto segment = new WgGeometryData;
|
auto segment = new WgGeometryData;
|
||||||
segment->positions.push(vlist.last());
|
segment->positions.push(vlist.last());
|
||||||
segments->geometries.push(segment);
|
splitted->geometries.push(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vlist.count >= 2) {
|
if (vlist.count >= 2) {
|
||||||
|
@ -422,40 +478,40 @@ void WgGeometryDataGroup::strokeSegments(const RenderShape& rshape, WgGeometryDa
|
||||||
WgPoint vcurr = vlist[0];
|
WgPoint vcurr = vlist[0];
|
||||||
while (icurr < vlist.count) {
|
while (icurr < vlist.count) {
|
||||||
if (ipatt % 2 == 0) {
|
if (ipatt % 2 == 0) {
|
||||||
segments->geometries.push(new WgGeometryData);
|
splitted->geometries.push(new WgGeometryData);
|
||||||
segments->geometries.last()->positions.push(vcurr);
|
splitted->geometries.last()->positions.push(vcurr);
|
||||||
}
|
}
|
||||||
float lcurr = rshape.stroke->dashPattern[ipatt];
|
float lcurr = stroke->dashPattern[ipatt];
|
||||||
while ((icurr < vlist.count) && (vlist[icurr].dist(vcurr) < lcurr)) {
|
while ((icurr < vlist.count) && (vlist[icurr].dist(vcurr) < lcurr)) {
|
||||||
lcurr -= vlist[icurr].dist(vcurr);
|
lcurr -= vlist[icurr].dist(vcurr);
|
||||||
vcurr = vlist[icurr];
|
vcurr = vlist[icurr];
|
||||||
icurr++;
|
icurr++;
|
||||||
if (ipatt % 2 == 0) segments->geometries.last()->positions.push(vcurr);
|
if (ipatt % 2 == 0) splitted->geometries.last()->positions.push(vcurr);
|
||||||
}
|
}
|
||||||
if (icurr < vlist.count) {
|
if (icurr < vlist.count) {
|
||||||
vcurr = vcurr + (vlist[icurr] - vlist[icurr-1]).normal() * lcurr;
|
vcurr = vcurr + (vlist[icurr] - vlist[icurr-1]).normal() * lcurr;
|
||||||
if (ipatt % 2 == 0) segments->geometries.last()->positions.push(vcurr);
|
if (ipatt % 2 == 0) splitted->geometries.last()->positions.push(vcurr);
|
||||||
}
|
}
|
||||||
ipatt = (ipatt + 1) % rshape.stroke->dashCnt;
|
ipatt = (ipatt + 1) % stroke->dashCnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgGeometryDataGroup::strokeSublines(const RenderShape& rshape, WgGeometryDataGroup* outlines, WgGeometryData* strokes)
|
void WgGeometryDataGroup::strokePolyline(WgGeometryDataGroup* polyline, WgGeometryData* strokes, RenderStroke *stroke)
|
||||||
{
|
{
|
||||||
float wdt = rshape.stroke->width / 2;
|
float wdt = stroke->width / 2;
|
||||||
for (uint32_t i = 0; i < outlines->geometries.count; i++) {
|
for (uint32_t i = 0; i < polyline->geometries.count; i++) {
|
||||||
auto outline = outlines->geometries[i];
|
auto outline = polyline->geometries[i];
|
||||||
|
|
||||||
// single point sub-path
|
// single point sub-path
|
||||||
if (outline->positions.count == 1) {
|
if (outline->positions.count == 1) {
|
||||||
if (rshape.stroke->cap == StrokeCap::Round) {
|
if (stroke->cap == StrokeCap::Round) {
|
||||||
strokes->appendCircle(outline->positions[0], wdt);
|
strokes->appendCircle(outline->positions[0], wdt);
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Butt) {
|
} else if (stroke->cap == StrokeCap::Butt) {
|
||||||
// for zero length sub-paths no stroke is rendered
|
// for zero length sub-paths no stroke is rendered
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Square) {
|
} else if (stroke->cap == StrokeCap::Square) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
outline->positions[0] + WgPoint(+wdt, +wdt),
|
outline->positions[0] + WgPoint(+wdt, +wdt),
|
||||||
outline->positions[0] + WgPoint(+wdt, -wdt),
|
outline->positions[0] + WgPoint(+wdt, -wdt),
|
||||||
|
@ -471,18 +527,18 @@ void WgGeometryDataGroup::strokeSublines(const RenderShape& rshape, WgGeometryDa
|
||||||
WgPoint v1 = outline->positions[1];
|
WgPoint v1 = outline->positions[1];
|
||||||
WgPoint dir0 = (v1 - v0).normal();
|
WgPoint dir0 = (v1 - v0).normal();
|
||||||
WgPoint nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
WgPoint nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
||||||
if (rshape.stroke->cap == StrokeCap::Round) {
|
if (stroke->cap == StrokeCap::Round) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v0 - nrm0 * wdt, v0 + nrm0 * wdt,
|
v0 - nrm0 * wdt, v0 + nrm0 * wdt,
|
||||||
v1 - nrm0 * wdt, v1 + nrm0 * wdt);
|
v1 - nrm0 * wdt, v1 + nrm0 * wdt);
|
||||||
strokes->appendCircle(outline->positions[0], wdt);
|
strokes->appendCircle(outline->positions[0], wdt);
|
||||||
strokes->appendCircle(outline->positions[1], wdt);
|
strokes->appendCircle(outline->positions[1], wdt);
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Butt) {
|
} else if (stroke->cap == StrokeCap::Butt) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v0 - nrm0 * wdt, v0 + nrm0 * wdt,
|
v0 - nrm0 * wdt, v0 + nrm0 * wdt,
|
||||||
v1 - nrm0 * wdt, v1 + nrm0 * wdt
|
v1 - nrm0 * wdt, v1 + nrm0 * wdt
|
||||||
);
|
);
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Square) {
|
} else if (stroke->cap == StrokeCap::Square) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v0 - nrm0 * wdt - dir0 * wdt, v0 + nrm0 * wdt - dir0 * wdt,
|
v0 - nrm0 * wdt - dir0 * wdt, v0 + nrm0 * wdt - dir0 * wdt,
|
||||||
v1 - nrm0 * wdt + dir0 * wdt, v1 + nrm0 * wdt + dir0 * wdt
|
v1 - nrm0 * wdt + dir0 * wdt, v1 + nrm0 * wdt + dir0 * wdt
|
||||||
|
@ -497,11 +553,11 @@ void WgGeometryDataGroup::strokeSublines(const RenderShape& rshape, WgGeometryDa
|
||||||
WgPoint v1 = outline->positions[1];
|
WgPoint v1 = outline->positions[1];
|
||||||
WgPoint dir0 = (v1 - v0).normal();
|
WgPoint dir0 = (v1 - v0).normal();
|
||||||
WgPoint nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
WgPoint nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
||||||
if (rshape.stroke->cap == StrokeCap::Round) {
|
if (stroke->cap == StrokeCap::Round) {
|
||||||
strokes->appendCircle(v0, wdt);
|
strokes->appendCircle(v0, wdt);
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Butt) {
|
} else if (stroke->cap == StrokeCap::Butt) {
|
||||||
// no cap needed
|
// no cap needed
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Square) {
|
} else if (stroke->cap == StrokeCap::Square) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v0 - nrm0 * wdt - dir0 * wdt,
|
v0 - nrm0 * wdt - dir0 * wdt,
|
||||||
v0 + nrm0 * wdt - dir0 * wdt,
|
v0 + nrm0 * wdt - dir0 * wdt,
|
||||||
|
@ -515,11 +571,11 @@ void WgGeometryDataGroup::strokeSublines(const RenderShape& rshape, WgGeometryDa
|
||||||
v1 = outline->positions[outline->positions.count - 1];
|
v1 = outline->positions[outline->positions.count - 1];
|
||||||
dir0 = (v1 - v0).normal();
|
dir0 = (v1 - v0).normal();
|
||||||
nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
nrm0 = WgPoint{ -dir0.y, +dir0.x };
|
||||||
if (rshape.stroke->cap == StrokeCap::Round) {
|
if (stroke->cap == StrokeCap::Round) {
|
||||||
strokes->appendCircle(v1, wdt);
|
strokes->appendCircle(v1, wdt);
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Butt) {
|
} else if (stroke->cap == StrokeCap::Butt) {
|
||||||
// no cap needed
|
// no cap needed
|
||||||
} else if (rshape.stroke->cap == StrokeCap::Square) {
|
} else if (stroke->cap == StrokeCap::Square) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v1 - nrm0 * wdt,
|
v1 - nrm0 * wdt,
|
||||||
v1 + nrm0 * wdt,
|
v1 + nrm0 * wdt,
|
||||||
|
@ -551,17 +607,17 @@ void WgGeometryDataGroup::strokeSublines(const RenderShape& rshape, WgGeometryDa
|
||||||
WgPoint dir1 = (v1 - v2).normal();
|
WgPoint dir1 = (v1 - v2).normal();
|
||||||
WgPoint nrm0 { -dir0.y, +dir0.x };
|
WgPoint nrm0 { -dir0.y, +dir0.x };
|
||||||
WgPoint nrm1 { +dir1.y, -dir1.x };
|
WgPoint nrm1 { +dir1.y, -dir1.x };
|
||||||
if (rshape.stroke->join == StrokeJoin::Round) {
|
if (stroke->join == StrokeJoin::Round) {
|
||||||
strokes->appendCircle(v1, wdt);
|
strokes->appendCircle(v1, wdt);
|
||||||
} else if (rshape.stroke->join == StrokeJoin::Bevel) {
|
} else if (stroke->join == StrokeJoin::Bevel) {
|
||||||
strokes->appendRect(
|
strokes->appendRect(
|
||||||
v1 - nrm0 * wdt, v1 - nrm1 * wdt,
|
v1 - nrm0 * wdt, v1 - nrm1 * wdt,
|
||||||
v1 + nrm1 * wdt, v1 + nrm0 * wdt
|
v1 + nrm1 * wdt, v1 + nrm0 * wdt
|
||||||
);
|
);
|
||||||
} else if (rshape.stroke->join == StrokeJoin::Miter) {
|
} else if (stroke->join == StrokeJoin::Miter) {
|
||||||
WgPoint nrm = (dir0 + dir1).normal();
|
WgPoint nrm = (dir0 + dir1).normal();
|
||||||
float cosine = nrm.dot(nrm0);
|
float cosine = nrm.dot(nrm0);
|
||||||
if ((cosine != 0.0f) && (abs(wdt / cosine) <= rshape.stroke->miterlimit * 2)) {
|
if ((cosine != 0.0f) && (abs(wdt / cosine) <= stroke->miterlimit * 2)) {
|
||||||
strokes->appendRect(v1 + nrm * (wdt / cosine), v1 + nrm0 * wdt, v1 + nrm1 * wdt, v1);
|
strokes->appendRect(v1 + nrm * (wdt / cosine), v1 + nrm0 * wdt, v1 + nrm1 * wdt, v1);
|
||||||
strokes->appendRect(v1 - nrm * (wdt / cosine), v1 - nrm0 * wdt, v1 - nrm1 * wdt, v1);
|
strokes->appendRect(v1 - nrm * (wdt / cosine), v1 - nrm0 * wdt, v1 - nrm1 * wdt, v1);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -94,6 +94,9 @@ struct WgGeometryData
|
||||||
void appendBlitBox();
|
void appendBlitBox();
|
||||||
void appendMesh(const RenderMesh* rmesh);
|
void appendMesh(const RenderMesh* rmesh);
|
||||||
|
|
||||||
|
WgPoint interpolate(float t, uint32_t& ind); // t = [0;1]
|
||||||
|
|
||||||
|
float getLength();
|
||||||
bool getClosestIntersection(WgPoint p1, WgPoint p2, WgPoint& pi, uint32_t& index);
|
bool getClosestIntersection(WgPoint p1, WgPoint p2, WgPoint& pi, uint32_t& index);
|
||||||
bool isCW(WgPoint p1, WgPoint p2, WgPoint p3);
|
bool isCW(WgPoint p1, WgPoint p2, WgPoint p3);
|
||||||
|
|
||||||
|
@ -117,9 +120,10 @@ struct WgGeometryDataGroup
|
||||||
void contours(WgGeometryDataGroup& outlines);
|
void contours(WgGeometryDataGroup& outlines);
|
||||||
void release();
|
void release();
|
||||||
private:
|
private:
|
||||||
static void decodePath(const RenderShape& rshape, WgGeometryDataGroup* outlines);
|
static void decodePath(const RenderShape& rshape, WgGeometryDataGroup* polyline);
|
||||||
static void strokeSegments(const RenderShape& rshape, WgGeometryDataGroup* outlines, WgGeometryDataGroup* segments);
|
static void trimPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* trimmed, RenderStroke *stroke);
|
||||||
static void strokeSublines(const RenderShape& rshape, WgGeometryDataGroup* outlines, WgGeometryData* strokes);
|
static void splitPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* splitted, RenderStroke *stroke);
|
||||||
|
static void strokePolyline(WgGeometryDataGroup* polyline, WgGeometryData* strokes, RenderStroke *stroke);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _TVG_WG_GEOMETRY_H_
|
#endif // _TVG_WG_GEOMETRY_H_
|
||||||
|
|
Loading…
Add table
Reference in a new issue