renderer: newly support the Lighten/Darken Masking options

Lighten is applied, where multiple masks intersect,
the highest transparency value is used.

Darken is applied, where multiple masks intersect,
the lowest transparency value is used.

Experimental API:
- CompositeMethod::LightenMask
- CompositeMethod::DarkenMask

issue: https://github.com/thorvg/thorvg/issues/2608
This commit is contained in:
Hermet Park 2024-08-06 21:03:16 +09:00
parent 82aa0c2bf4
commit b20d5da552
4 changed files with 24 additions and 11 deletions

View file

@ -165,7 +165,9 @@ enum class CompositeMethod
AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) (Experimental API)
SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) (Experimental API)
IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) (Experimental API)
DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) (Experimental API)
DifferenceMask, ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) (Experimental API)
LightenMask, ///< Where multiple masks intersect, the highest transparency value is used. (Experimental API)
DarkenMask ///< Where multiple masks intersect, the lowest transparency value is used. (Experimental API)
};

View file

@ -71,14 +71,8 @@ CompositeMethod LottieParser::getMaskMethod(bool inversed)
case 's': return CompositeMethod::SubtractMask;
case 'i': return CompositeMethod::IntersectMask;
case 'f': return CompositeMethod::DifferenceMask;
case 'l': {
TVGLOG("LOTTIE", "Mask Lighten is not supported");
return CompositeMethod::None;
}
case 'd': {
TVGLOG("LOTTIE", "Mask Darken is not supported");
return CompositeMethod::None;
}
case 'l': return CompositeMethod::LightenMask;
case 'd': return CompositeMethod::DarkenMask;
default: return CompositeMethod::None;
}
}

View file

@ -194,10 +194,21 @@ static inline uint8_t _opMaskDifference(uint8_t s, uint8_t d, uint8_t a)
}
static inline uint8_t _opMaskLighten(uint8_t s, uint8_t d, uint8_t a)
{
return (s > d) ? s : d;
}
static inline uint8_t _opMaskDarken(uint8_t s, uint8_t d, uint8_t a)
{
return (s < d) ? s : d;
}
static inline bool _direct(CompositeMethod method)
{
//subtract & Intersect allows the direct composition
if (method == CompositeMethod::SubtractMask || method == CompositeMethod::IntersectMask) return true;
if (method == CompositeMethod::SubtractMask || method == CompositeMethod::IntersectMask || method == CompositeMethod::DarkenMask) return true;
return false;
}
@ -209,6 +220,8 @@ static inline SwMask _getMaskOp(CompositeMethod method)
case CompositeMethod::SubtractMask: return _opMaskSubtract;
case CompositeMethod::DifferenceMask: return _opMaskDifference;
case CompositeMethod::IntersectMask: return _opMaskIntersect;
case CompositeMethod::LightenMask: return _opMaskLighten;
case CompositeMethod::DarkenMask: return _opMaskDarken;
default: return nullptr;
}
}

View file

@ -323,6 +323,8 @@ static inline bool MASK_REGION_MERGING(CompositeMethod method)
//these might expand the rendering region
case CompositeMethod::AddMask:
case CompositeMethod::DifferenceMask:
case CompositeMethod::LightenMask:
case CompositeMethod::DarkenMask:
return true;
default:
TVGERR("RENDERER", "Unsupported Composite Method! = %d", (int)method);
@ -356,6 +358,8 @@ static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod* renderer, Composi
case CompositeMethod::DifferenceMask:
case CompositeMethod::SubtractMask:
case CompositeMethod::IntersectMask:
case CompositeMethod::LightenMask:
case CompositeMethod::DarkenMask:
return ColorSpace::Grayscale8;
//TODO: Optimize Luma/InvLuma colorspace to Grayscale8
case CompositeMethod::LumaMask: