GraphiteEditor / GraphiteEditor/Graphite

Graphite clipping masks do not support SVG luminance masks ?

未关闭
#4,341 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Rust
星标
27.2k
派生
1.3k
平均合并
20 小时 5 分钟
30 天内合并 PR
57

描述

## Description

Graphite’s clipping-mask rendering pipeline treats masks exclusively as alpha masks.
SVG masks can instead use luminance, where the rendered color brightness determines
visibility.

This causes imported luminance masks to render incorrectly even after support for
reading `usvg::Group::mask()` is implemented.

## Dependency

This issue depends on adding SVG mask importing through `usvg::Group::mask()`.

Until that importer support exists, the reproduction also fails because the entire mask
is discarded. Once mask importing is connected, this issue isolates the remaining
alpha-versus-luminance rendering failure.

## Reproduction

Import `HameronsDocs/svg-luminance-mask-debug.svg`.

The fixture contains:

- One solid blue rectangle.
- An explicitly declared `mask-type="luminance"`.
- An opaque white rectangle that reveals the artwork.
- An opaque black circle that creates a transparent hole.
- No gradients, transforms, strokes, clip paths, filters, or fill-rule dependencies.

```svg

```
## Expected behavior

Image

The SVG imports as a blue square with a transparent circular hole in its center.

Under luminance-mask semantics:

- White produces full visibility.
- Black produces full transparency.
- Gray or colored content produces partial visibility based on luminance and alpha.

## Actual behavior

Image

Graphite’s alpha-only mask behavior treats both the white rectangle and black circle as
fully opaque because both have alpha 1.

The resulting artwork is therefore a solid blue square without a transparent hole.

## Root cause

The resolved usvg::Mask preserves its semantic mode through usvg::Mask::kind(), which
distinguishes MaskType::Luminance from MaskType::Alpha.

Graphite does not carry that distinction through its document graph or renderers:

- The SVG renderer emits generated masks with mask-type="alpha".
- The Vello renderer composites clipping masks using source alpha through SrcIn.
- Mask colors are therefore ignored when calculating visibility.
- Graphite’s internal MaskType currently distinguishes Clip from Mask, not luminance
from alpha.

Simply importing the SVG mask geometry through the existing clipping-mask mechanism is
insufficient because opaque black and opaque white produce identical alpha values.

## Suggested scope

Preserve the resolved SVG mask mode and support luminance-to-alpha conversion
consistently across Graphite’s SVG and Vello renderers.

This should remain separate from the issue that connects usvg::Group::mask() to the
importer because it requires renderer and document-attribute support rather than only
importer wiring.

The SVG specification defines luminance as the initial value for elements, so
masks without an explicit mask-type must also use luminance semantics.

Reference: https://www.w3.org/TR/css-masking-1/#the-mask-type

## Acceptance criteria

- The isolated fixture renders as a blue square with a transparent circular hole.
- Explicit mask-type="alpha" masks retain existing alpha behavior.
- Explicit mask-type="luminance" masks use color luminance multiplied by source alpha.
- Masks without mask-type default to luminance.
- Black, white, gray, colored, and partially transparent mask content behave correctly.
- SVG and Vello rendering produce equivalent results.
- SVG output preserves or emits the correct mask type.
- Regression tests cover both alpha and luminance masks.

贡献指南

这个仓库没有索引到贡献指南

调研方向

首先通过 usvg::Group::mask() 跟踪 SVG 蒙版的导入,然后继续跟踪已解析的蒙版模式在 Graphite 文档图、SVG 渲染器和 Vello 渲染器中的流转。使用 HameronsDocs/svg-luminance-mask-debug.svg 进行复现。完成的标准是:包括默认亮度情况在内的 alpha 蒙版和亮度蒙版都能一致地渲染,并且两个渲染器都有回归测试覆盖。

由索引模型根据 Issue 内容生成。

评估

技术栈
rust
领域
computer-graphics
Issue 类型
缺陷
难度
5/5
预计耗时
一周以上
活跃度
冷清
描述清晰度
描述清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。