mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
common: changed premultiplied color policy.
Some user have no idea of premultiplied alpha concept, We suggest more user-friendly interfaces so that they don't confuse it. Now, this pre-multipying is acommplished by backend engines. Change-Id: Ifd84d56361cb56a8b98240bbd16690accf370bad
This commit is contained in:
parent
9979e2cbf7
commit
9f6b5eb59e
5 changed files with 32 additions and 8 deletions
|
@ -244,6 +244,12 @@ static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t
|
|||
}
|
||||
|
||||
|
||||
static inline uint8_t COLOR_ALPHA_MULTIPLY(uint32_t c, uint32_t a)
|
||||
{
|
||||
return (c * a) >> 8;
|
||||
}
|
||||
|
||||
|
||||
int64_t mathMultiply(int64_t a, int64_t b);
|
||||
int64_t mathDivide(int64_t a, int64_t b);
|
||||
int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
|
||||
|
@ -290,7 +296,8 @@ bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, ui
|
|||
bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
bool rasterClear(Surface& surface);
|
||||
|
||||
inline void rasterARGB32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
||||
|
||||
static inline void rasterARGB32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
||||
{
|
||||
#ifdef THORVG_AVX_VECTOR_SUPPORT
|
||||
int32_t align = (8 - (offset % 8)) % 8;
|
||||
|
|
|
@ -46,7 +46,11 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata)
|
|||
|
||||
if (pColors->a < 255) fill->translucent = true;
|
||||
|
||||
auto rgba = COLOR_ARGB_JOIN(pColors->r, pColors->g, pColors->b, pColors->a);
|
||||
auto r = COLOR_ALPHA_MULTIPLY(pColors->r, pColors->a);
|
||||
auto g = COLOR_ALPHA_MULTIPLY(pColors->g, pColors->a);
|
||||
auto b = COLOR_ALPHA_MULTIPLY(pColors->b, pColors->a);
|
||||
|
||||
auto rgba = COLOR_ARGB_JOIN(r, g, b, pColors->a);
|
||||
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
||||
auto pos = 1.5f * inc;
|
||||
uint32_t i = 0;
|
||||
|
@ -65,7 +69,12 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata)
|
|||
assert(curr && next);
|
||||
auto delta = 1.0f / (next->offset - curr->offset);
|
||||
if (next->a < 255) fill->translucent = true;
|
||||
auto rgba2 = COLOR_ARGB_JOIN(next->r, next->g, next->b, next->a);
|
||||
|
||||
auto r = COLOR_ALPHA_MULTIPLY(next->r, next->a);
|
||||
auto g = COLOR_ALPHA_MULTIPLY(next->g, next->a);
|
||||
auto b = COLOR_ALPHA_MULTIPLY(next->b, next->a);
|
||||
|
||||
auto rgba2 = COLOR_ARGB_JOIN(r, g, b, next->a);
|
||||
|
||||
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
||||
auto t = (pos - curr->offset) * delta;
|
||||
|
|
|
@ -285,6 +285,10 @@ bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id)
|
|||
|
||||
bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
r = COLOR_ALPHA_MULTIPLY(r, a);
|
||||
g = COLOR_ALPHA_MULTIPLY(g, a);
|
||||
b = COLOR_ALPHA_MULTIPLY(b, a);
|
||||
|
||||
//Fast Track
|
||||
if (shape.rect) {
|
||||
auto region = _clipRegion(surface, shape.bbox);
|
||||
|
@ -300,6 +304,10 @@ bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, ui
|
|||
|
||||
bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
r = COLOR_ALPHA_MULTIPLY(r, a);
|
||||
g = COLOR_ALPHA_MULTIPLY(g, a);
|
||||
b = COLOR_ALPHA_MULTIPLY(b, a);
|
||||
|
||||
if (a == 255) return _rasterSolidRle(surface, shape.strokeRle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
return _rasterTranslucentRle(surface, shape.strokeRle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
//Prepare Circle
|
||||
auto shape2 = tvg::Shape::gen();
|
||||
shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH
|
||||
shape2->fill(170, 170, 0, 170); //r, g, b, a
|
||||
shape2->fill(255, 255, 0, 170); //r, g, b, a
|
||||
if (canvas->push(move(shape2)) != tvg::Result::Success) return;
|
||||
|
||||
//Prepare Ellipse
|
||||
auto shape3 = tvg::Shape::gen();
|
||||
shape3->appendCircle(400, 400, 250, 100); //cx, cy, radiusW, radiusH
|
||||
shape3->fill(100, 100, 100, 100); //r, g, b, a
|
||||
shape3->fill(255, 255, 255, 100); //r, g, b, a
|
||||
if (canvas->push(move(shape3)) != tvg::Result::Success) return;
|
||||
|
||||
//Prepare Star
|
||||
|
@ -41,7 +41,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
shape4->lineTo(26, 361);
|
||||
shape4->lineTo(146, 343);
|
||||
shape4->close();
|
||||
shape4->fill(200, 0, 200, 200);
|
||||
shape4->fill(255, 0, 200, 200);
|
||||
if (canvas->push(move(shape4)) != tvg::Result::Success) return;
|
||||
|
||||
//Prepare Opaque Ellipse
|
||||
|
|
|
@ -58,7 +58,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
shape4->lineTo(-173, 12.5);
|
||||
shape4->lineTo(-53, -5.5);
|
||||
shape4->close();
|
||||
shape4->fill(0, 0, 127, 127);
|
||||
shape4->fill(0, 0, 255, 127);
|
||||
shape4->stroke(3); //width
|
||||
shape4->stroke(0, 0, 255, 255); //r, g, b, a
|
||||
scene2->push(move(shape4));
|
||||
|
@ -78,7 +78,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
shape5->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy);
|
||||
shape5->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius);
|
||||
shape5->close();
|
||||
shape5->fill(127, 0, 0, 127);
|
||||
shape5->fill(255, 0, 0, 127);
|
||||
scene2->push(move(shape5));
|
||||
|
||||
scene2->translate(500, 350);
|
||||
|
|
Loading…
Add table
Reference in a new issue