mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
composite: Support Inverse Luma Masking
The CompositeMethod now includes the newly supported InvLumaMask option: The source pixels are converted to grayscale (luma values), and the complement of the target's pixels is alpha blended. As a result, only the part of the source where the grayscale is not covered by the target is visible. @APIs: CompositeMethod::InvLumaMask @Example: examples/InvLumaMasking.cpp @Issue: https://github.com/thorvg/thorvg/issues/404
This commit is contained in:
parent
6f715b46a7
commit
21c7debf14
4 changed files with 52 additions and 1 deletions
|
@ -170,7 +170,8 @@ enum class CompositeMethod
|
|||
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
|
||||
AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
|
||||
InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
|
||||
LumaMask ///< The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible. @since 0.9
|
||||
LumaMask, ///< The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible. @since 0.9
|
||||
InvLumaMask ///< The source pixels are converted to the grayscale (luma value) and the complement to the target's pixels are alpha blended. As a result, only the part of the source which grayscale is not covered by the target is visible. @BETA_API
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -242,6 +242,7 @@ struct SwBlender
|
|||
{
|
||||
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
uint8_t (*luma)(uint8_t* c);
|
||||
uint8_t (*iluma)(uint8_t* c);
|
||||
};
|
||||
|
||||
struct SwCompositor;
|
||||
|
|
|
@ -76,6 +76,18 @@ static inline uint8_t _argbLuma(uint8_t* c)
|
|||
}
|
||||
|
||||
|
||||
static inline uint8_t _abgrInvLuma(uint8_t* c)
|
||||
{
|
||||
return ~_abgrLuma(c);
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t _argbInvLuma(uint8_t* c)
|
||||
{
|
||||
return ~_argbLuma(c);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
return (a << 24 | b << 16 | g << 8 | r);
|
||||
|
@ -234,6 +246,8 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uin
|
|||
return _rasterMaskedRect(surface, region, r, g, b, a, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterMaskedRect(surface, region, r, g, b, a, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterMaskedRect(surface, region, r, g, b, a, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (a == 255) {
|
||||
|
@ -342,6 +356,8 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
|
|||
return _rasterMaskedRle(surface, rle, r, g, b, a, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterMaskedRle(surface, rle, r, g, b, a, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterMaskedRle(surface, rle, r, g, b, a, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (a == 255) {
|
||||
|
@ -373,6 +389,8 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
|
|||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
|
||||
|
@ -596,6 +614,8 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
|
|||
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (surface->compositor->method == CompositeMethod::AlphaMask) {
|
||||
|
@ -604,6 +624,8 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
|
|||
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.iluma);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -724,6 +746,8 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
|
|||
return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (surface->compositor->method == CompositeMethod::AlphaMask) {
|
||||
|
@ -732,6 +756,8 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
|
|||
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.iluma);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -755,6 +781,8 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
|
|||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, nullptr);
|
||||
|
@ -771,6 +799,8 @@ static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image,
|
|||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, nullptr);
|
||||
|
@ -963,6 +993,8 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
|
|||
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (surface->compositor->method == CompositeMethod::AlphaMask) {
|
||||
|
@ -971,6 +1003,8 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
|
|||
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.iluma);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1089,6 +1123,8 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
|
|||
return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (surface->compositor->method == CompositeMethod::AlphaMask) {
|
||||
|
@ -1097,6 +1133,8 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
|
|||
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.iluma);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1204,6 +1242,8 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
|
||||
|
@ -1311,6 +1351,8 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
|
|||
return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
|
||||
|
@ -1401,6 +1443,8 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
|
||||
|
@ -1507,6 +1551,8 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
|
|||
return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
|
||||
return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.luma);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvLumaMask) {
|
||||
return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.iluma);
|
||||
}
|
||||
} else {
|
||||
if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
|
||||
|
@ -1536,9 +1582,11 @@ bool rasterCompositor(SwSurface* surface)
|
|||
if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) {
|
||||
surface->blender.join = _abgrJoin;
|
||||
surface->blender.luma = _abgrLuma;
|
||||
surface->blender.iluma = _abgrInvLuma;
|
||||
} else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) {
|
||||
surface->blender.join = _argbJoin;
|
||||
surface->blender.luma = _argbLuma;
|
||||
surface->blender.iluma = _argbInvLuma;
|
||||
} else {
|
||||
TVGERR("SW_ENGINE", "Unsupported Colorspace(%d) is expected!", surface->cs);
|
||||
return false;
|
||||
|
|
|
@ -262,6 +262,7 @@ static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, Composi
|
|||
case CompositeMethod::InvAlphaMask:
|
||||
return ColorSpace::Grayscale8;
|
||||
case CompositeMethod::LumaMask:
|
||||
case CompositeMethod::InvLumaMask:
|
||||
return renderer.colorSpace();
|
||||
default:
|
||||
TVGERR("COMMON", "Unsupported Composite Size! = %d", (int)method);
|
||||
|
|
Loading…
Add table
Reference in a new issue