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
|
||||
//***********************************************************************
|
||||
|
||||
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)
|
||||
{
|
||||
releaseMeshes(context);
|
||||
strokeFirst = false;
|
||||
strokeFirst = rshape.stroke ? rshape.stroke->strokeFirst : false;
|
||||
|
||||
static WgPolyline polyline;
|
||||
polyline.clear();
|
||||
|
@ -296,6 +305,7 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha
|
|||
}
|
||||
// proceed last polyline
|
||||
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);
|
||||
meshGroupShapes.append(context, polyline);
|
||||
meshGroupShapesBBox.append(context, pmin, pmax);
|
||||
updateBBox(pmin, pmax);
|
||||
}
|
||||
// generate strokes geometry
|
||||
if ((polyline->pts.count >= 1) && rstroke) {
|
||||
|
@ -342,12 +353,15 @@ void WgRenderDataShape::releaseMeshes(WgContext &context)
|
|||
meshGroupStrokes.release(context);
|
||||
meshGroupShapesBBox.release(context);
|
||||
meshGroupShapes.release(context);
|
||||
pMin = {0.0f, 0.0f };
|
||||
pMax = {0.0f, 0.0f };
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataShape::release(WgContext& context)
|
||||
{
|
||||
releaseMeshes(context);
|
||||
meshDataBBox.release(context);
|
||||
renderSettingsStroke.release(context);
|
||||
renderSettingsShape.release(context);
|
||||
WgRenderDataPaint::release(context);
|
||||
|
|
|
@ -97,10 +97,15 @@ struct WgRenderDataShape: public WgRenderDataPaint
|
|||
WgRenderSettings renderSettingsStroke{};
|
||||
WgMeshDataGroup meshGroupShapes{};
|
||||
WgMeshDataGroup meshGroupShapesBBox{};
|
||||
WgMeshData meshDataBBox{};
|
||||
WgMeshDataGroup meshGroupStrokes{};
|
||||
WgMeshDataGroup meshGroupStrokesBBox{};
|
||||
WgPoint pMin{};
|
||||
WgPoint pMax{};
|
||||
bool strokeFirst{};
|
||||
FillRule fillRule{};
|
||||
|
||||
void updateBBox(WgPoint pmin, WgPoint pmax);
|
||||
void updateMeshes(WgContext& context, const RenderShape& rshape);
|
||||
void updateMeshes(WgContext& context, const WgPolyline* polyline, const RenderStroke* rstroke);
|
||||
void releaseMeshes(WgContext& context);
|
||||
|
|
|
@ -82,9 +82,15 @@ void WgRenderStorage::renderShape(WgContext& context, WgRenderDataShape* renderD
|
|||
{
|
||||
assert(renderData);
|
||||
assert(mRenderPassEncoder);
|
||||
// draw strokes
|
||||
if (renderData->strokeFirst)
|
||||
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)
|
||||
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(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)
|
||||
{
|
||||
assert(renderData);
|
||||
|
|
|
@ -64,7 +64,8 @@ public:
|
|||
WgBindGroupOpacity* opacity);
|
||||
void antialias(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc);
|
||||
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 dispatchWorkgroups(WGPUComputePassEncoder computePassEncoder);
|
||||
|
|
|
@ -93,6 +93,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
WgShaderTypeMat4x4f modelMat(transform);
|
||||
WgShaderTypeBlendSettings blendSettings(mTargetSurface.cs, opacity);
|
||||
renderDataShape->bindGroupPaint.initialize(mContext.device, mContext.queue, modelMat, blendSettings);
|
||||
renderDataShape->fillRule = rshape.rule;
|
||||
}
|
||||
|
||||
// setup fill settings
|
||||
|
|
Loading…
Add table
Reference in a new issue