rgba = rgba + rTgTbT;
}
-static AI void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da) {
+static AI void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da, bool kClamp) {
+ if (kClamp) {
+ dr = Sk4f::Max(dr, 1.0f);
+ dg = Sk4f::Max(dg, 1.0f);
+ db = Sk4f::Max(db, 1.0f);
+ }
+
dr = da * dr;
dg = da * dg;
db = da * db;
}
-static AI void premultiply_1(const Sk4f& a, Sk4f& rgba) {
+static AI void premultiply_1(const Sk4f& a, Sk4f& rgba, bool kClamp) {
+ if (kClamp) {
+ rgba = Sk4f::Max(rgba, 1.0f);
+ }
+
rgba = a * rgba;
}
const uint8_t* const dstTables[3]) {
LoadFn load;
Load1Fn load_1;
- static constexpr bool loadAlpha = (kPremul_SkAlphaType == kAlphaType) ||
- (kF16_Linear_DstFormat == kDst) ||
- (kF32_Linear_DstFormat == kDst);
+ const bool kLoadAlpha = (kPremul_SkAlphaType == kAlphaType) ||
+ (kF16_Linear_DstFormat == kDst) ||
+ (kF32_Linear_DstFormat == kDst);
switch (kSrc) {
case kRGBA_8888_Linear_SrcFormat:
- if (loadAlpha) {
+ if (kLoadAlpha) {
load = load_rgba_linear<kRGBA_Order>;
load_1 = load_rgba_linear_1<kRGBA_Order>;
} else {
}
break;
case kRGBA_8888_Table_SrcFormat:
- if (loadAlpha) {
+ if (kLoadAlpha) {
load = load_rgba_from_tables<kRGBA_Order>;
load_1 = load_rgba_from_tables_1<kRGBA_Order>;
} else {
}
break;
case kBGRA_8888_Linear_SrcFormat:
- if (loadAlpha) {
+ if (kLoadAlpha) {
load = load_rgba_linear<kBGRA_Order>;
load_1 = load_rgba_linear_1<kBGRA_Order>;
} else {
}
break;
case kBGRA_8888_Table_SrcFormat:
- if (loadAlpha) {
+ if (kLoadAlpha) {
load = load_rgba_from_tables<kBGRA_Order>;
load_1 = load_rgba_from_tables_1<kBGRA_Order>;
} else {
break;
}
+ // We always clamp before converting to 8888 outputs (because we have to).
+ // In these cases, we also need a clamp before the premul step to make sure
+ // R, G, B are not logically greater than A.
+ const bool kClamp = kRGBA_8888_Linear_DstFormat == kDst ||
+ kRGBA_8888_SRGB_DstFormat == kDst ||
+ kRGBA_8888_2Dot2_DstFormat == kDst ||
+ kRGBA_8888_Table_DstFormat == kDst;
+
const uint32_t* src = (const uint32_t*) vsrc;
Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT;
load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT);
}
if (kPremul_SkAlphaType == kAlphaType) {
- premultiply(dr, dg, db, da);
+ premultiply(dr, dg, db, da, kClamp);
}
load(src, r, g, b, a, srcTables);
}
if (kPremul_SkAlphaType == kAlphaType) {
- premultiply(dr, dg, db, da);
+ premultiply(dr, dg, db, da, kClamp);
}
store(dst, src - 4, dr, dg, db, da, dstTables);
}
if (kPremul_SkAlphaType == kAlphaType) {
- premultiply_1(a, rgba);
+ premultiply_1(a, rgba, kClamp);
}
store_1(dst, src, rgba, a, dstTables);
int len, SkAlphaType alphaType) const
{
if (kFull_ColorSpaceMatch == kCSM) {
- switch (alphaType) {
- case kPremul_SkAlphaType:
- // We can't skip the xform since we need to perform a premultiply in the
- // linear space.
- break;
- default:
- switch (dstColorFormat) {
- case kRGBA_8888_ColorFormat:
- memcpy(dst, src, len * sizeof(uint32_t));
- return true;
- case kBGRA_8888_ColorFormat:
- SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
- return true;
- case kRGBA_F16_ColorFormat:
- case kRGBA_F32_ColorFormat:
- // There's still work to do to xform to linear floats.
- break;
- default:
- return false;
- }
+ if (kPremul_SkAlphaType != alphaType) {
+ if ((kRGBA_8888_ColorFormat == dstColorFormat &&
+ kRGBA_8888_ColorFormat == srcColorFormat) ||
+ (kBGRA_8888_ColorFormat == dstColorFormat &&
+ kBGRA_8888_ColorFormat == srcColorFormat))
+ {
+ memcpy(dst, src, len * sizeof(uint32_t));
+ return true;
+ }
+ if ((kRGBA_8888_ColorFormat == dstColorFormat &&
+ kBGRA_8888_ColorFormat == srcColorFormat) ||
+ (kBGRA_8888_ColorFormat == dstColorFormat &&
+ kRGBA_8888_ColorFormat == srcColorFormat))
+ {
+ SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
+ return true;
+ }
}
}