mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
wg_engine: Text support
[issues 1479: Text](#1479) EvenOdd fill rule reorganized: using global bbox of whole path for fill
This commit is contained in:
parent
7581b08c69
commit
46041111d8
5 changed files with 55 additions and 4 deletions
|
@ -264,10 +264,19 @@ void WgRenderDataPaint::release(WgContext& context)
|
||||||
// WgRenderDataShape
|
// WgRenderDataShape
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
||||||
|
void WgRenderDataShape::updateBBox(WgPoint pmin, WgPoint pmax)
|
||||||
|
{
|
||||||
|
pMin.x = std::min(pMin.x, pmin.x);
|
||||||
|
pMin.y = std::min(pMin.y, pmin.y);
|
||||||
|
pMax.x = std::max(pMax.x, pmax.x);
|
||||||
|
pMax.y = std::max(pMax.y, pmax.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rshape)
|
void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rshape)
|
||||||
{
|
{
|
||||||
releaseMeshes(context);
|
releaseMeshes(context);
|
||||||
strokeFirst = false;
|
strokeFirst = rshape.stroke ? rshape.stroke->strokeFirst : false;
|
||||||
|
|
||||||
static WgPolyline polyline;
|
static WgPolyline polyline;
|
||||||
polyline.clear();
|
polyline.clear();
|
||||||
|
@ -296,6 +305,7 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha
|
||||||
}
|
}
|
||||||
// proceed last polyline
|
// proceed last polyline
|
||||||
updateMeshes(context, &polyline, rshape.stroke);
|
updateMeshes(context, &polyline, rshape.stroke);
|
||||||
|
meshDataBBox.update(context, pMin, pMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,6 +318,7 @@ void WgRenderDataShape::updateMeshes(WgContext& context, const WgPolyline* polyl
|
||||||
polyline->getBBox(pmin, pmax);
|
polyline->getBBox(pmin, pmax);
|
||||||
meshGroupShapes.append(context, polyline);
|
meshGroupShapes.append(context, polyline);
|
||||||
meshGroupShapesBBox.append(context, pmin, pmax);
|
meshGroupShapesBBox.append(context, pmin, pmax);
|
||||||
|
updateBBox(pmin, pmax);
|
||||||
}
|
}
|
||||||
// generate strokes geometry
|
// generate strokes geometry
|
||||||
if ((polyline->pts.count >= 1) && rstroke) {
|
if ((polyline->pts.count >= 1) && rstroke) {
|
||||||
|
@ -342,12 +353,15 @@ void WgRenderDataShape::releaseMeshes(WgContext &context)
|
||||||
meshGroupStrokes.release(context);
|
meshGroupStrokes.release(context);
|
||||||
meshGroupShapesBBox.release(context);
|
meshGroupShapesBBox.release(context);
|
||||||
meshGroupShapes.release(context);
|
meshGroupShapes.release(context);
|
||||||
|
pMin = {0.0f, 0.0f };
|
||||||
|
pMax = {0.0f, 0.0f };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataShape::release(WgContext& context)
|
void WgRenderDataShape::release(WgContext& context)
|
||||||
{
|
{
|
||||||
releaseMeshes(context);
|
releaseMeshes(context);
|
||||||
|
meshDataBBox.release(context);
|
||||||
renderSettingsStroke.release(context);
|
renderSettingsStroke.release(context);
|
||||||
renderSettingsShape.release(context);
|
renderSettingsShape.release(context);
|
||||||
WgRenderDataPaint::release(context);
|
WgRenderDataPaint::release(context);
|
||||||
|
|
|
@ -97,10 +97,15 @@ struct WgRenderDataShape: public WgRenderDataPaint
|
||||||
WgRenderSettings renderSettingsStroke{};
|
WgRenderSettings renderSettingsStroke{};
|
||||||
WgMeshDataGroup meshGroupShapes{};
|
WgMeshDataGroup meshGroupShapes{};
|
||||||
WgMeshDataGroup meshGroupShapesBBox{};
|
WgMeshDataGroup meshGroupShapesBBox{};
|
||||||
|
WgMeshData meshDataBBox{};
|
||||||
WgMeshDataGroup meshGroupStrokes{};
|
WgMeshDataGroup meshGroupStrokes{};
|
||||||
WgMeshDataGroup meshGroupStrokesBBox{};
|
WgMeshDataGroup meshGroupStrokesBBox{};
|
||||||
|
WgPoint pMin{};
|
||||||
|
WgPoint pMax{};
|
||||||
bool strokeFirst{};
|
bool strokeFirst{};
|
||||||
|
FillRule fillRule{};
|
||||||
|
|
||||||
|
void updateBBox(WgPoint pmin, WgPoint pmax);
|
||||||
void updateMeshes(WgContext& context, const RenderShape& rshape);
|
void updateMeshes(WgContext& context, const RenderShape& rshape);
|
||||||
void updateMeshes(WgContext& context, const WgPolyline* polyline, const RenderStroke* rstroke);
|
void updateMeshes(WgContext& context, const WgPolyline* polyline, const RenderStroke* rstroke);
|
||||||
void releaseMeshes(WgContext& context);
|
void releaseMeshes(WgContext& context);
|
||||||
|
|
|
@ -82,9 +82,15 @@ void WgRenderStorage::renderShape(WgContext& context, WgRenderDataShape* renderD
|
||||||
{
|
{
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(mRenderPassEncoder);
|
assert(mRenderPassEncoder);
|
||||||
|
// draw strokes
|
||||||
if (renderData->strokeFirst)
|
if (renderData->strokeFirst)
|
||||||
drawStroke(context, renderData, blendType);
|
drawStroke(context, renderData, blendType);
|
||||||
drawShape(context, renderData, blendType);
|
// draw shape
|
||||||
|
if(renderData->fillRule == FillRule::Winding)
|
||||||
|
drawShapeWinding(context, renderData, blendType);
|
||||||
|
else if(renderData->fillRule == FillRule::EvenOdd)
|
||||||
|
drawShapeEvenOdd(context, renderData, blendType);
|
||||||
|
// draw strokes
|
||||||
if (!renderData->strokeFirst)
|
if (!renderData->strokeFirst)
|
||||||
drawStroke(context, renderData, blendType);
|
drawStroke(context, renderData, blendType);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +107,7 @@ void WgRenderStorage::renderPicture(WgContext& context, WgRenderDataPicture* ren
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderStorage::drawShape(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
|
void WgRenderStorage::drawShapeWinding(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
|
||||||
{
|
{
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(mRenderPassEncoder);
|
assert(mRenderPassEncoder);
|
||||||
|
@ -126,6 +132,30 @@ void WgRenderStorage::drawShape(WgContext& context, WgRenderDataShape* renderDat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgRenderStorage::drawShapeEvenOdd(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
|
||||||
|
{
|
||||||
|
assert(renderData);
|
||||||
|
assert(mRenderPassEncoder);
|
||||||
|
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||||
|
// draw shape geometry
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0);
|
||||||
|
// draw to stencil (first pass)
|
||||||
|
mPipelines->fillShape.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint);
|
||||||
|
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++)
|
||||||
|
renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder);
|
||||||
|
// fill shape geometry (second pass)
|
||||||
|
uint8_t blend = (uint8_t)blendType;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||||
|
if (settings.fillType == WgRenderSettingsType::Solid)
|
||||||
|
mPipelines->solid[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupSolid);
|
||||||
|
else if (settings.fillType == WgRenderSettingsType::Linear)
|
||||||
|
mPipelines->linear[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupLinear);
|
||||||
|
else if (settings.fillType == WgRenderSettingsType::Radial)
|
||||||
|
mPipelines->radial[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupRadial);
|
||||||
|
renderData->meshDataBBox.drawFan(context, mRenderPassEncoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderStorage::drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
|
void WgRenderStorage::drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
|
||||||
{
|
{
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
|
|
|
@ -64,7 +64,8 @@ public:
|
||||||
WgBindGroupOpacity* opacity);
|
WgBindGroupOpacity* opacity);
|
||||||
void antialias(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc);
|
void antialias(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc);
|
||||||
private:
|
private:
|
||||||
void drawShape(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
|
void drawShapeWinding(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
|
||||||
|
void drawShapeEvenOdd(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
|
||||||
void drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
|
void drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
|
||||||
|
|
||||||
void dispatchWorkgroups(WGPUComputePassEncoder computePassEncoder);
|
void dispatchWorkgroups(WGPUComputePassEncoder computePassEncoder);
|
||||||
|
|
|
@ -93,6 +93,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
||||||
WgShaderTypeMat4x4f modelMat(transform);
|
WgShaderTypeMat4x4f modelMat(transform);
|
||||||
WgShaderTypeBlendSettings blendSettings(mTargetSurface.cs, opacity);
|
WgShaderTypeBlendSettings blendSettings(mTargetSurface.cs, opacity);
|
||||||
renderDataShape->bindGroupPaint.initialize(mContext.device, mContext.queue, modelMat, blendSettings);
|
renderDataShape->bindGroupPaint.initialize(mContext.device, mContext.queue, modelMat, blendSettings);
|
||||||
|
renderDataShape->fillRule = rshape.rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup fill settings
|
// setup fill settings
|
||||||
|
|
Loading…
Add table
Reference in a new issue