mirror of
https://github.com/darlinghq/darling-cocotron.git
synced 2024-11-26 21:40:44 +00:00
652 lines
18 KiB
Objective-C
652 lines
18 KiB
Objective-C
/*------------------------------------------------------------------------
|
|
*
|
|
* Derivative of the OpenVG 1.0.1 Reference Implementation
|
|
* -------------------------------------
|
|
*
|
|
* Copyright (c) 2007 The Khronos Group Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and /or associated documentation files
|
|
* (the "Materials "), to deal in the Materials without restriction,
|
|
* including without limitation the rights to use, copy, modify, merge,
|
|
* publish, distribute, sublicense, and/or sell copies of the Materials,
|
|
* and to permit persons to whom the Materials are furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Materials.
|
|
*
|
|
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
|
|
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
#import <Onyx2D/O2argb32f.h>
|
|
|
|
/*-------------------------------------------------------------------*/ /*!
|
|
* \brief Applies paint, image drawing, masking and blending at pixel
|
|
(x,y).
|
|
* \param
|
|
* \return
|
|
* \note premultiplied blending formulas
|
|
//src
|
|
a = asrc
|
|
r = rsrc
|
|
//src over
|
|
a = asrc + adst * (1-asrc)
|
|
r = rsrc + rdst * (1-asrc)
|
|
//dst over
|
|
a = asrc * (1-adst) + adst
|
|
r = rsrc * (1-adst) + adst
|
|
//src in
|
|
a = asrc * adst
|
|
r = rsrc * adst
|
|
//dst in
|
|
a = adst * asrc
|
|
r = rdst * asrc
|
|
//multiply
|
|
a = asrc + adst * (1-asrc)
|
|
r = rsrc * (1-adst) + rdst * (1-asrc) + rsrc * rdst
|
|
//screen
|
|
a = asrc + adst * (1-asrc)
|
|
r = rsrc + rdst - rsrc * rdst
|
|
//darken
|
|
a = asrc + adst * (1-asrc)
|
|
r = MIN(rsrc + rdst * (1-asrc), rdst + rsrc * (1-adst))
|
|
//lighten
|
|
a = asrc + adst * (1-asrc)
|
|
r = MAX(rsrc + rdst * (1-asrc), rdst + rsrc * (1-adst))
|
|
//additive
|
|
a = MIN(asrc+adst,1)
|
|
r = rsrc + rdst
|
|
*/
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
static inline O2Float colorFromTemp(O2Float c, O2Float q, O2Float p) {
|
|
if (6.0 * c < 1)
|
|
c = p + (q - p) * 6.0 * c;
|
|
else if (2.0 * c < 1)
|
|
c = q;
|
|
else if (3.0 * c < 2)
|
|
c = p + (q - p) * ((2.0 / 3.0) - c) * 6.0;
|
|
else
|
|
c = p;
|
|
return c;
|
|
}
|
|
|
|
static inline void HSLToRGB(O2Float hue, O2Float saturation, O2Float luminance,
|
|
O2Float32 *redp, O2Float32 *greenp,
|
|
O2Float32 *bluep)
|
|
{
|
|
O2Float red = luminance, green = luminance, blue = luminance;
|
|
|
|
if (saturation != 0) {
|
|
O2Float p, q;
|
|
|
|
if (luminance < 0.5)
|
|
q = luminance * (1 + saturation);
|
|
else
|
|
q = luminance + saturation - (luminance * saturation);
|
|
p = 2 * luminance - q;
|
|
|
|
red = hue + 1.0 / 3.0;
|
|
if (red < 0)
|
|
red += 1.0;
|
|
green = hue;
|
|
if (green < 0)
|
|
green += 1.0;
|
|
blue = hue - 1.0 / 3.0;
|
|
if (blue < 0)
|
|
blue += 1.0;
|
|
|
|
red = colorFromTemp(red, q, p);
|
|
green = colorFromTemp(green, q, p);
|
|
blue = colorFromTemp(blue, q, p);
|
|
}
|
|
|
|
*redp = red;
|
|
*greenp = green;
|
|
*bluep = blue;
|
|
}
|
|
|
|
static inline void RGBToHSL(O2Float r, O2Float g, O2Float b, O2Float *huep,
|
|
O2Float *saturationp, O2Float *luminancep)
|
|
{
|
|
O2Float hue = 0, saturation = 0, luminance, min, max;
|
|
|
|
max = MAX(r, MAX(g, b));
|
|
min = MIN(r, MIN(g, b));
|
|
if (max == min)
|
|
hue = 0;
|
|
else if (max == r && g >= b)
|
|
hue = 60 * ((g - b) / (max - min));
|
|
else if (max == r && g < b)
|
|
hue = 60 * ((g - b) / (max - min)) + 360;
|
|
else if (max == g)
|
|
hue = 60 * ((b - r) / (max - min)) + 120;
|
|
else if (max == b)
|
|
hue = 60 * ((r - g) / (max - min)) + 240;
|
|
|
|
luminance = (max + min) / 2.0;
|
|
if (max == min)
|
|
saturation = 0;
|
|
else if (luminance <= 0.5)
|
|
saturation = (max - min) / (max + min);
|
|
else
|
|
saturation = (max - min) / (2 - (max + min));
|
|
|
|
if (huep != NULL)
|
|
*huep = fmod(hue, 360) / 360.0;
|
|
if (saturationp != NULL)
|
|
*saturationp = saturation;
|
|
if (luminancep != NULL)
|
|
*luminancep = luminance;
|
|
}
|
|
|
|
void O2BlendSpanNormal_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r + d.r * (1.0f - s.a);
|
|
r.g = s.g + d.g * (1.0f - s.a);
|
|
r.b = s.b + d.b * (1.0f - s.a);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanMultiply_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * (1.0f - d.a + d.r) + d.r * (1.0f - s.a);
|
|
r.g = s.g * (1.0f - d.a + d.g) + d.g * (1.0f - s.a);
|
|
r.b = s.b * (1.0f - d.a + d.b) + d.b * (1.0f - s.a);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanScreen_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r + d.r - s.r * d.r;
|
|
r.g = s.g + d.g - s.g * d.g;
|
|
r.b = s.b + d.b - s.b * d.b;
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanOverlay_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
O2Float max = RI_MAX(s.r, RI_MAX(s.g, s.b));
|
|
O2Float min = RI_MIN(s.r, RI_MIN(s.g, s.b));
|
|
O2Float lum = (max + min) / 2 * (1.0 - d.a);
|
|
if (lum <= 0.5)
|
|
r.r = s.r * (1.0f - d.a + d.r) + d.r * (1.0f - s.a);
|
|
else
|
|
r.r = s.r + d.r - s.r * d.r;
|
|
|
|
if (lum <= 0.5)
|
|
r.g = s.g * (1.0f - d.a + d.g) + d.g * (1.0f - s.a);
|
|
else
|
|
r.g = s.g + d.g - s.g * d.g;
|
|
|
|
if (lum <= 0.5)
|
|
r.b = s.b * (1.0f - d.a + d.b) + d.b * (1.0f - s.a);
|
|
else
|
|
r.b = s.b + d.b - s.b * d.b;
|
|
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanDarken_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = RI_MIN(s.r + d.r * (1.0f - s.a), d.r + s.r * (1.0f - d.a));
|
|
r.g = RI_MIN(s.g + d.g * (1.0f - s.a), d.g + s.g * (1.0f - d.a));
|
|
r.b = RI_MIN(s.b + d.b * (1.0f - s.a), d.b + s.b * (1.0f - d.a));
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanLighten_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = RI_MAX(s.r + d.r * (1.0f - s.a), d.r + s.r * (1.0f - d.a));
|
|
r.g = RI_MAX(s.g + d.g * (1.0f - s.a), d.g + s.g * (1.0f - d.a));
|
|
r.b = RI_MAX(s.b + d.b * (1.0f - s.a), d.b + s.b * (1.0f - d.a));
|
|
// although the statement below is equivalent to r.a = s.a + d.a * (1.0f
|
|
// - s.a) in practice there can be a very slight difference because of
|
|
// the max operation in the blending formula that may cause color to
|
|
// exceed alpha. Because of this, we compute the result both ways and
|
|
// return the maximum.
|
|
r.a = RI_MAX(s.a + d.a * (1.0f - s.a), d.a + s.a * (1.0f - d.a));
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanColorDodge_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = (s.r == 1.0f) ? 1.0f : RI_MIN(1.0f, d.r / (1.0f - s.r));
|
|
r.g = (s.g == 1.0f) ? 1.0f : RI_MIN(1.0f, d.g / (1.0f - s.g));
|
|
r.b = (s.b == 1.0f) ? 1.0f : RI_MIN(1.0f, d.b / (1.0f - s.b));
|
|
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanColorBurn_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = (s.r == 0) ? 0 : 1.0 - RI_MIN(1.0, (1.0 - d.r) / s.r);
|
|
r.g = (s.g == 0) ? 0 : 1.0 - RI_MIN(1.0, (1.0 - d.g) / s.g);
|
|
r.b = (s.b == 0) ? 0 : 1.0 - RI_MIN(1.0, (1.0 - d.b) / s.b);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanHardLight_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r = d;
|
|
|
|
if (s.r <= 0.5) {
|
|
s.r *= 2;
|
|
r.r = s.r * (1.0f - d.a + d.r) + d.r * (1.0f - s.a);
|
|
} else {
|
|
s.r = 2 * s.r - 1;
|
|
r.r = s.r + d.r - s.r * d.r;
|
|
}
|
|
|
|
if (s.g <= 0.5) {
|
|
s.g *= 2;
|
|
r.g = s.g * (1.0f - d.a + d.g) + d.g * (1.0f - s.a);
|
|
} else {
|
|
s.g = 2 * s.g - 1;
|
|
r.g = s.g + d.g - s.g * d.g;
|
|
}
|
|
|
|
if (s.b <= 0.5) {
|
|
s.b *= 2;
|
|
r.b = s.b * (1.0f - d.a + d.b) + d.b * (1.0f - s.a);
|
|
} else {
|
|
s.b = 2 * s.b - 1;
|
|
r.b = s.b + d.b - s.b * d.b;
|
|
}
|
|
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanSoftLight_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
// O2argb32f s=src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r = d;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanDifference_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r + d.r - 2 * (RI_MIN(s.r * d.a, d.r * s.a));
|
|
r.g = s.g + d.g - 2 * (RI_MIN(s.g * d.a, d.g * s.a));
|
|
r.b = s.b + d.b - 2 * (RI_MIN(s.b * d.a, d.b * s.a));
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanExclusion_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = (s.r * d.a + d.r * s.a - 2 * s.r * d.r) + s.r * (1 - d.a) +
|
|
d.r * (1 - s.a);
|
|
r.g = (s.g * d.a + d.g * s.a - 2 * s.g * d.g) + s.g * (1 - d.a) +
|
|
d.g * (1 - s.a);
|
|
r.b = (s.b * d.a + d.b * s.a - 2 * s.b * d.b) + s.b * (1 - d.a) +
|
|
d.b * (1 - s.a);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanHue_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
O2Float sh, ss, sl;
|
|
O2Float dh, ds, dl;
|
|
|
|
RGBToHSL(s.r, s.g, s.b, &sh, &ss, &sl);
|
|
RGBToHSL(d.r, d.g, d.b, &dh, &ds, &dl);
|
|
HSLToRGB(sh, ds, dl, &r.r, &r.g, &r.b);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanSaturation_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
O2Float sh, ss, sl;
|
|
O2Float dh, ds, dl;
|
|
|
|
RGBToHSL(s.r, s.g, s.b, &sh, &ss, &sl);
|
|
RGBToHSL(d.r, d.g, d.b, &dh, &ds, &dl);
|
|
HSLToRGB(dh, ss, dl, &r.r, &r.g, &r.b);
|
|
r.a = s.a + d.a * (1.0f - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanColor_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
// O2argb32f s=src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r = d;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanLuminosity_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
// O2argb32f s=src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r = d;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanClear_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f r;
|
|
|
|
r.r = 0;
|
|
r.g = 0;
|
|
r.b = 0;
|
|
r.a = 0;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanCopy_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
// do nothing src already contains values
|
|
}
|
|
|
|
void O2BlendSpanSourceIn_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * d.a;
|
|
r.g = s.g * d.a;
|
|
r.b = s.b * d.a;
|
|
r.a = s.a * d.a;
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanSourceOut_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * (1.0 - d.a);
|
|
r.g = s.g * (1.0 - d.a);
|
|
r.b = s.b * (1.0 - d.a);
|
|
r.a = s.a * (1.0 - d.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanSourceAtop_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * d.a + d.r * (1.0 - s.a);
|
|
r.g = s.g * d.a + d.g * (1.0 - s.a);
|
|
r.b = s.b * d.a + d.b * (1.0 - s.a);
|
|
r.a = s.a * d.a + d.a * (1.0 - s.a);
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanDestinationOver_ffff(O2argb32f *src, O2argb32f *dst, int length)
|
|
{
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * (1.0f - d.a) + d.r;
|
|
r.g = s.g * (1.0f - d.a) + d.g;
|
|
r.b = s.b * (1.0f - d.a) + d.b;
|
|
r.a = s.a * (1.0f - d.a) + d.a;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanDestinationIn_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = d.r * s.a;
|
|
r.g = d.g * s.a;
|
|
r.b = d.b * s.a;
|
|
r.a = d.a * s.a;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
void O2BlendSpanDestinationOut_ffff(O2argb32f *src, O2argb32f *dst, int length)
|
|
{
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = d.r * (1.0 - s.a);
|
|
r.g = d.g * (1.0 - s.a);
|
|
r.b = d.b * (1.0 - s.a);
|
|
r.a = d.a * (1.0 - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanDestinationAtop_ffff(O2argb32f *src, O2argb32f *dst, int length)
|
|
{
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * (1.0 - d.a) + d.r * s.a;
|
|
r.g = s.g * (1.0 - d.a) + d.g * s.a;
|
|
r.b = s.b * (1.0 - d.a) + d.b * s.a;
|
|
r.a = s.a * (1.0 - d.a) + d.a * s.a;
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanXOR_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = s.r * (1.0 - d.a) + d.r * (1.0 - s.a);
|
|
r.g = s.g * (1.0 - d.a) + d.g * (1.0 - s.a);
|
|
r.b = s.b * (1.0 - d.a) + d.b * (1.0 - s.a);
|
|
r.a = s.a * (1.0 - d.a) + d.a * (1.0 - s.a);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanPlusDarker_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// broken
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
#if 1
|
|
// Doc.s say: R = MAX(0, (1 - D) + (1 - S)). No workie.
|
|
r.r = RI_MAX(0, (1 - d.r) + (1 - s.r));
|
|
r.g = RI_MAX(0, (1 - d.g) + (1 - s.g));
|
|
r.b = RI_MAX(0, (1 - d.b) + (1 - s.b));
|
|
r.a = RI_MAX(0, (1 - d.a) + (1 - s.a));
|
|
#endif
|
|
src[i] = r;
|
|
}
|
|
}
|
|
|
|
void O2BlendSpanPlusLighter_ffff(O2argb32f *src, O2argb32f *dst, int length) {
|
|
// Passes Visual Test
|
|
// Doc.s say: R = MIN(1, S + D). That works
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
O2argb32f s = src[i];
|
|
O2argb32f d = dst[i];
|
|
O2argb32f r;
|
|
|
|
r.r = RI_MIN(s.r + d.r, 1.0f);
|
|
r.g = RI_MIN(s.g + d.g, 1.0f);
|
|
r.b = RI_MIN(s.b + d.b, 1.0f);
|
|
r.a = RI_MIN(s.a + d.a, 1.0f);
|
|
|
|
src[i] = r;
|
|
}
|
|
}
|