feat(render): handle mesh-gradient + shader fills across editor consumers
vendor/jian ff39a41 added PenFill::MeshGradient / PenFill::Shader plus SceneGradient::Mesh and SceneNode.shader; every exhaustive match over those types stopped compiling. Cover them with faithful conservative semantics: opacity getters/setters treat the new bodies like their gradient siblings, variable binding walks mesh vertex stops (shader uniforms are untyped — left alone), canvas paint degrades mesh to its first vertex colour until the RenderBackend grows a mesh method, the property panel reports the neutral Solid type (no lossy conversion offered), and lint contrast checks skip both like image fills.
This commit is contained in:
parent
0ba60361d4
commit
061296c779
|
|
@ -186,6 +186,9 @@ fn first_solid_color(fills: Option<&Vec<PenFill>>) -> Option<String> {
|
|||
}
|
||||
}
|
||||
PenFill::Image(_) => continue,
|
||||
// Mesh gradients / SkSL shaders have no single representative
|
||||
// color for contrast checks — treated like image fills.
|
||||
PenFill::MeshGradient(_) | PenFill::Shader(_) => continue,
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -348,6 +348,8 @@ pub fn first_solid_fill_opacity(node: &PenNode) -> f32 {
|
|||
PenFill::Solid(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::LinearGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::RadialGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::MeshGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::Shader(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::Image(b) => b.opacity.unwrap_or(1.0),
|
||||
})
|
||||
.unwrap_or(1.0)
|
||||
|
|
@ -367,6 +369,8 @@ pub fn first_solid_stroke_opacity(node: &PenNode) -> f32 {
|
|||
PenFill::Solid(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::LinearGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::RadialGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::MeshGradient(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::Shader(b) => b.opacity.unwrap_or(1.0),
|
||||
PenFill::Image(b) => b.opacity.unwrap_or(1.0),
|
||||
})
|
||||
.unwrap_or(1.0)
|
||||
|
|
@ -475,6 +479,8 @@ pub fn set_primary_fill_opacity(node: &mut PenNode, opacity: f32) -> bool {
|
|||
PenFill::Solid(b) => b.opacity = Some(opacity),
|
||||
PenFill::LinearGradient(b) => b.opacity = Some(opacity),
|
||||
PenFill::RadialGradient(b) => b.opacity = Some(opacity),
|
||||
PenFill::MeshGradient(b) => b.opacity = Some(opacity),
|
||||
PenFill::Shader(b) => b.opacity = Some(opacity),
|
||||
PenFill::Image(b) => b.opacity = Some(opacity),
|
||||
}
|
||||
true
|
||||
|
|
@ -618,6 +624,10 @@ pub fn fill_type_of(fill: &PenFill) -> FillType {
|
|||
PenFill::Solid(_) => FillType::Solid,
|
||||
PenFill::LinearGradient(_) => FillType::LinearGradient,
|
||||
PenFill::RadialGradient(_) => FillType::RadialGradient,
|
||||
// The property panel has no mesh-gradient / shader picker rows
|
||||
// yet — report the neutral default so the panel stays usable
|
||||
// without offering a lossy conversion.
|
||||
PenFill::MeshGradient(_) | PenFill::Shader(_) => FillType::Solid,
|
||||
PenFill::Image(_) => FillType::Image,
|
||||
}
|
||||
}
|
||||
|
|
@ -692,6 +702,9 @@ fn fill_hex(fill: &PenFill) -> Option<&str> {
|
|||
PenFill::Solid(body) => Some(body.color.as_str()),
|
||||
PenFill::LinearGradient(body) => body.stops.first().map(|s| s.color.as_str()),
|
||||
PenFill::RadialGradient(body) => body.stops.first().map(|s| s.color.as_str()),
|
||||
PenFill::MeshGradient(body) => body.stops.first().map(|s| s.color.as_str()),
|
||||
// A shader has no representative colour.
|
||||
PenFill::Shader(_) => None,
|
||||
PenFill::Image(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,6 +242,18 @@ pub(crate) fn paint_gradient_rect(
|
|||
*opacity,
|
||||
);
|
||||
}
|
||||
SceneGradient::Mesh {
|
||||
colors, opacity, ..
|
||||
} => {
|
||||
// No mesh-gradient method on the RenderBackend yet —
|
||||
// degrade to the first vertex colour (same fallback the
|
||||
// scene builder bakes into `SceneNode.fill`).
|
||||
if let Some(first) = colors.first() {
|
||||
let mut c = *first;
|
||||
c.a = (c.a * opacity).clamp(0.0, 1.0);
|
||||
cx.backend.fill_round_rect(rect, corner_radius, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -729,7 +729,9 @@ pub(crate) fn paint_svg_path_node(
|
|||
d, world_rect, &flat, *gx, *cy, *radius, *opacity,
|
||||
);
|
||||
}
|
||||
None => {
|
||||
// Mesh gradients have no svg-path shader yet — fall back to
|
||||
// the node's resolved `fill` colour like the no-gradient path.
|
||||
Some(SceneGradient::Mesh { .. }) | None => {
|
||||
if let Some(fill) = node.fill {
|
||||
cx.backend.fill_svg_path_in_rect(d, world_rect, fill);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1160,6 +1160,12 @@ fn fills_of(node: &PenNode) -> Vec<FillSummary> {
|
|||
b.stops.first().map(|s| s.color.as_str()),
|
||||
b.opacity.unwrap_or(1.0),
|
||||
),
|
||||
PenFill::MeshGradient(b) => (
|
||||
b.stops.first().map(|s| s.color.as_str()),
|
||||
b.opacity.unwrap_or(1.0),
|
||||
),
|
||||
// Shader fills have no representative colour.
|
||||
PenFill::Shader(b) => (None, b.opacity.unwrap_or(1.0)),
|
||||
PenFill::Image(b) => (None, b.opacity.unwrap_or(1.0)),
|
||||
};
|
||||
FillSummary {
|
||||
|
|
|
|||
|
|
@ -105,6 +105,14 @@ fn bind_fills(fills: &mut [PenFill], refs: &ColorRefs) {
|
|||
bind_color_string(&mut stop.color, refs);
|
||||
}
|
||||
}
|
||||
PenFill::MeshGradient(body) => {
|
||||
for stop in &mut body.stops {
|
||||
bind_color_string(&mut stop.color, refs);
|
||||
}
|
||||
}
|
||||
// Shader colours live in untyped uniform values — leave
|
||||
// them alone rather than guess which uniforms are colours.
|
||||
PenFill::Shader(_) => {}
|
||||
PenFill::Image(_) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,6 +216,9 @@ fn node_payload_to_scene(
|
|||
.gradient
|
||||
.as_ref()
|
||||
.map(|g| scale_gradient_opacity(payload_gradient_to_scene(g), cum_opacity)),
|
||||
// The payload path doesn't carry SkSL shader bodies yet — the
|
||||
// scene painter degrades to the resolved `fill` colour.
|
||||
shader: None,
|
||||
stroke: node.stroke.as_ref().map(|s| {
|
||||
let mut st = scene_stroke(s, &node_id, var_table);
|
||||
st.color = mul_alpha(st.color, cum_opacity);
|
||||
|
|
@ -377,6 +380,17 @@ fn scale_gradient_opacity(g: SceneGradient, k: f32) -> SceneGradient {
|
|||
opacity: (opacity * k).clamp(0.0, 1.0),
|
||||
stops,
|
||||
},
|
||||
SceneGradient::Mesh {
|
||||
rows,
|
||||
cols,
|
||||
colors,
|
||||
opacity,
|
||||
} => SceneGradient::Mesh {
|
||||
rows,
|
||||
cols,
|
||||
colors,
|
||||
opacity: (opacity * k).clamp(0.0, 1.0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -255,6 +255,18 @@ fn first_solid_color(fills: Option<&[PenFill]>) -> Option<[f32; 4]> {
|
|||
}
|
||||
}
|
||||
}
|
||||
PenFill::MeshGradient(body) => {
|
||||
if let Some(stop) = body.stops.first() {
|
||||
if let Some(rgba) = parse_hex(&stop.color) {
|
||||
return Some(apply_alpha(rgba, body.opacity));
|
||||
}
|
||||
}
|
||||
}
|
||||
PenFill::Shader(body) => {
|
||||
// Payload painters can't run SkSL — mid-gray fallback
|
||||
// (mirrors SceneShader::fallback's default).
|
||||
return Some(apply_alpha([0.5, 0.5, 0.5, 1.0], body.opacity));
|
||||
}
|
||||
PenFill::Image(_) => {
|
||||
return Some([0.85, 0.86, 0.88, 1.0]);
|
||||
}
|
||||
|
|
|
|||
2
vendor/jian
vendored
2
vendor/jian
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 8ed9a89fa46b13bb26524e3176b708b2ed6b2970
|
||||
Subproject commit ff39a4163edee286fa7bd8c6afc969bcca2cbaec
|
||||
Loading…
Reference in a new issue