Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 9c876db

Browse files
Merge pull request #5769 from livecodeian/bugfix-19926
[[ Bug 19926 ]] Fix incorrectly masked rendering of legacy gradients when scaled
2 parents c9dd00c + f6acb29 commit 9c876db

File tree

3 files changed

+15
-177
lines changed

3 files changed

+15
-177
lines changed

docs/notes/bugfix-19926.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Fix incorrect rendering of legacy gradients when stack scaling is applied

libgraphics/src/graphics-internal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,6 @@ class MCGLegacyGradientShader : public SkShader
484484

485485
private:
486486
int32_t m_y;
487-
uint8_t *m_mask;
488487
MCGradientCombiner_t *m_gradient_combiner;
489488

490489
typedef SkShader::Context INHERITED;

libgraphics/src/legacygradients.cpp

Lines changed: 14 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct MCCombiner
117117
void (*begin)(MCCombiner *self, int4 y);
118118
void (*advance)(MCCombiner *self, int4 y);
119119
void (*blend)(MCCombiner *self, int4 fx, int4 tx, uint1 value);
120-
void (*combine)(MCCombiner *self, int4 fx, int4 tx, uint1 *mask);
120+
void (*combine)(MCCombiner *self, int4 fx, int4 tx);
121121
void (*end)(MCCombiner *self);
122122
};
123123

@@ -364,99 +364,7 @@ template<MCGradientFillKind x_type> static inline int4 compute_index(int4 p_x, i
364364
return t_index;
365365
}
366366

367-
template<MCGradientFillKind x_type> static void MCGradientFillBlend(MCCombiner *_self, int4 fx, int4 tx, uint1 alpha)
368-
{
369-
MCGradientAffineCombiner *self = (MCGradientAffineCombiner*)_self;
370-
uint4 *d;
371-
uint4 s;
372-
373-
d = self -> bits;
374-
375-
int4 t_index;
376-
int4 t_x = self->x_inc + self->x_coef_a * ((int4)fx);
377-
int4 t_y = self->y_inc + self->y_coef_a * ((int4)fx);
378-
379-
int4 t_min = (int4)self->ramp[0].offset;
380-
int4 t_max = (int4)self->ramp[self->ramp_length - 1].offset;
381-
382-
if (fx == tx) return;
383-
384-
bool t_mirror = self->mirror;
385-
uint4 t_repeat = self->repeat;
386-
387-
if (alpha == 255)
388-
{
389-
uint4 t_stop_pos = 0;
390-
391-
t_index = compute_index<x_type>(t_x, t_y, t_mirror, t_repeat);
392-
while (fx < tx)
393-
{
394-
if (t_index <= t_min)
395-
{
396-
s = self->ramp[0].hw_color;
397-
s = packed_scale_bounded(s | 0xFF000000, s >> 24);
398-
while (t_index <= t_min)
399-
{
400-
d[fx] = packed_scale_bounded(d[fx], 255 - (s >> 24)) + s;
401-
fx += 1;
402-
if (fx == tx)
403-
return;
404-
t_x += self->x_coef_a;
405-
t_y += self->y_coef_a;
406-
t_index = compute_index<x_type>(t_x, t_y, t_mirror, t_repeat);
407-
}
408-
}
409-
410-
if (t_index >= t_max)
411-
{
412-
s = self->ramp[self->ramp_length - 1].hw_color;
413-
s = packed_scale_bounded(s | 0xFF000000, s >> 24);
414-
while (t_index >= t_max)
415-
{
416-
d[fx] = packed_scale_bounded(d[fx], 255 - (s >> 24)) + s;
417-
fx += 1;
418-
if (fx == tx)
419-
return;
420-
t_x += self->x_coef_a;
421-
t_y += self->y_coef_a;
422-
t_index = compute_index<x_type>(t_x, t_y, t_mirror, t_repeat);
423-
}
424-
}
425-
426-
while (t_index >= t_min && t_index <= t_max)
427-
{
428-
MCGradientFillStop *t_current_stop = &self->ramp[t_stop_pos];
429-
int4 t_current_offset = t_current_stop->offset;
430-
int4 t_current_difference = t_current_stop->difference;
431-
uint4 t_current_color = t_current_stop->hw_color;
432-
MCGradientFillStop *t_next_stop = &self->ramp[t_stop_pos+1];
433-
int4 t_next_offset = t_next_stop->offset;
434-
uint4 t_next_color = t_next_stop->hw_color;
435-
436-
while (t_next_offset >= t_index && t_current_offset <= t_index)
437-
{
438-
uint1 b = ((t_index - t_current_offset) * t_current_difference) >> STOP_DIFF_PRECISION ;
439-
uint1 a = 255 - b;
440-
441-
s = packed_bilinear_bounded(t_current_color, a, t_next_color, b);
442-
d[fx] = packed_bilinear_bounded(d[fx], 255 - (s >> 24), s | 0xFF000000, s >> 24);
443-
fx += 1;
444-
if (fx == tx)
445-
return;
446-
t_x += self->x_coef_a;
447-
t_y += self->y_coef_a;
448-
t_index = compute_index<x_type>(t_x, t_y, t_mirror, t_repeat);
449-
}
450-
if (t_current_offset > t_index && t_stop_pos > 0)
451-
t_stop_pos -= 1;
452-
else if (t_next_offset < t_index && t_stop_pos < (self->ramp_length - 1))
453-
t_stop_pos += 1;
454-
}
455-
}
456-
}
457-
}
458-
459-
template<MCGradientFillKind x_type> static void MCGradientFillCombine(MCCombiner *_self, int4 fx, int4 tx, uint1 *mask)
367+
template<MCGradientFillKind x_type> static void MCGradientFillCombine(MCCombiner *_self, int4 fx, int4 tx)
460368
{
461369
MCGradientAffineCombiner *self = (MCGradientAffineCombiner*)_self;
462370
uint4 *d;
@@ -487,7 +395,7 @@ template<MCGradientFillKind x_type> static void MCGradientFillCombine(MCCombiner
487395
s = self->ramp[0].hw_color;
488396
while (t_index <= t_min)
489397
{
490-
uint4 sa = packed_scale_bounded(s | 0xFF000000, ((s >> 24) * *mask++) / 255);
398+
uint4 sa = packed_scale_bounded(s | 0xFF000000, (s >> 24));
491399
d[fx] = packed_scale_bounded(d[fx], 255 - (sa >> 24)) + sa;
492400
fx += 1;
493401
if (fx == tx)
@@ -503,7 +411,7 @@ template<MCGradientFillKind x_type> static void MCGradientFillCombine(MCCombiner
503411
s = self->ramp[self->ramp_length - 1].hw_color;
504412
while (t_index >= t_max)
505413
{
506-
uint4 sa = packed_scale_bounded(s | 0xFF000000, ((s >> 24) * *mask++) / 255);
414+
uint4 sa = packed_scale_bounded(s | 0xFF000000, (s >> 24));
507415
d[fx] = packed_scale_bounded(d[fx], 255 - (sa >> 24)) + sa;
508416
fx += 1;
509417
if (fx == tx)
@@ -530,7 +438,7 @@ template<MCGradientFillKind x_type> static void MCGradientFillCombine(MCCombiner
530438
uint1 a = 255 - b;
531439

532440
s = packed_bilinear_bounded(t_current_color, a, t_next_color, b);
533-
uint4 sa = packed_scale_bounded(s | 0xFF000000, ((s >> 24) * *mask++) / 255);
441+
uint4 sa = packed_scale_bounded(s | 0xFF000000, (s >> 24));
534442
d[fx] = packed_scale_bounded(d[fx], 255 - (sa >> 24)) + sa;
535443
fx += 1;
536444
if (fx == tx)
@@ -633,71 +541,7 @@ template<MCGradientFillKind x_type> static void blend_row(MCCombiner *_self, uin
633541
}
634542
}
635543

636-
static void gradient_bilinear_affine_combiner_end(MCCombiner *_self)
637-
{
638-
MCGradientAffineCombiner *self = (MCGradientAffineCombiner*)_self;
639-
delete self->buffer;
640-
}
641-
642-
template<MCGradientFillKind x_type> static void MCGradientFillBilinearBlend(MCCombiner *_self, uint4 fx, uint4 tx, uint1 alpha)
643-
{
644-
MCGradientAffineCombiner *self = (MCGradientAffineCombiner*)_self;
645-
uint4 *d;
646-
uint4 s;
647-
648-
d = self -> bits;
649-
650-
if (fx == tx) return;
651-
652-
uint4 *t_buffer = self->buffer;
653-
uint4 t_bufflen = self->buffer_width;
654-
655-
int4 x_a, x_b, x_inc;
656-
int4 y_a, y_b, y_inc;
657-
x_a = self->x_coef_a; x_b = self->x_coef_b; x_inc = self->x_inc;
658-
y_a = self->y_coef_a; y_b = self->y_coef_b; y_inc = self->y_inc;
659-
self->x_coef_a /= GRADIENT_AA_SCALE; self->x_coef_b /= GRADIENT_AA_SCALE;
660-
self->y_coef_a /= GRADIENT_AA_SCALE; self->y_coef_b /= GRADIENT_AA_SCALE;
661-
662-
uint4 dx = (tx - fx) * GRADIENT_AA_SCALE;
663-
uint4 t_fx = fx * GRADIENT_AA_SCALE;
664-
for (int i = 0; i < GRADIENT_AA_SCALE; i++)
665-
{
666-
blend_row<x_type>(self, t_fx, t_fx + dx, t_buffer);
667-
t_buffer += t_bufflen;
668-
self->x_inc += self->x_coef_b;
669-
self->y_inc += self->y_coef_b;
670-
}
671-
672-
self->x_coef_a = x_a; self->x_coef_b = x_b; self->x_inc = x_inc;
673-
self->y_coef_a = y_a; self->y_coef_b = y_b; self->y_inc = y_inc;
674-
675-
uint4 i = 0;
676-
if (alpha == 255)
677-
{
678-
for (; fx < tx; fx++)
679-
{
680-
uint4 u;
681-
uint4 v;
682-
683-
#if GRADIENT_AA_SCALE == 2
684-
// unroll for GRADIENT_AA_SCALE == 2
685-
u = (self->buffer[i*2] & 0xFF00FF) + (self->buffer[i*2 + 1] & 0xFF00FF) + \
686-
(self->buffer[t_bufflen + i*2] & 0xFF00FF) + (self->buffer[t_bufflen + i*2 + 1] & 0xFF00FF);
687-
v = ((self->buffer[i*2] >> 8) & 0xFF00FF) + ((self->buffer[i*2 + 1] >> 8) & 0xFF00FF) + \
688-
((self->buffer[t_bufflen + i*2] >> 8) & 0xFF00FF) + ((self->buffer[t_bufflen + i*2 + 1] >> 8) & 0xFF00FF);
689-
u = (u >> 2) & 0xFF00FF;
690-
v = (v << 6) & 0xFF00FF00;
691-
#endif
692-
i++;
693-
694-
s = u | v;
695-
d[fx] = packed_bilinear_bounded(d[fx], 255 - (s >> 24), s | 0xFF000000, s >> 24);
696-
}
697-
}
698-
}
699-
700-
template<MCGradientFillKind x_type> static void MCGradientFillBilinearCombine(MCCombiner *_self, int4 fx, int4 tx, uint1* mask)
544+
template<MCGradientFillKind x_type> static void MCGradientFillBilinearCombine(MCCombiner *_self, int4 fx, int4 tx)
701545
{
702546
MCGradientAffineCombiner *self = (MCGradientAffineCombiner*)_self;
703547
uint4 *d;
@@ -743,7 +587,7 @@ template<MCGradientFillKind x_type> static void MCGradientFillBilinearCombine(MC
743587
i++;
744588

745589
s = u | v;
746-
uint1 alpha = (s >> 24) * (*mask++) / 255;
590+
uint1 alpha = (s >> 24);
747591
d[fx] = packed_bilinear_bounded(d[fx], 255 - alpha, s | 0xFF000000, alpha);
748592
}
749593
}
@@ -760,7 +604,7 @@ void MCGradientFillDeleteCombiner(MCGradientAffineCombiner *p_combiner)
760604
MCMemoryDelete(p_combiner);
761605
}
762606

763-
MCGradientAffineCombiner *MCGradientFillCreateCombiner(MCGGradientRef p_gradient_ref, MCGRectangle &r_clip, const MCGAffineTransform &p_transform)
607+
MCGradientAffineCombiner *MCGradientFillCreateCombiner(MCGGradientRef p_gradient_ref, const MCGRectangle &p_clip, const MCGAffineTransform &p_transform)
764608
{
765609
// MM-2014-07-31: [[ ThreadedRendering ]] Removed use of single static combiner to make things thread safe.
766610
MCAutoCustomPointer<MCGradientAffineCombiner, MCGradientFillDeleteCombiner> t_combiner;
@@ -849,11 +693,11 @@ MCGradientAffineCombiner *MCGradientFillCreateCombiner(MCGGradientRef p_gradient
849693
{
850694
(*t_combiner) -> x_coef_a = STOP_INT_MAX * -wy / d;
851695
(*t_combiner) -> x_coef_b = STOP_INT_MAX * wx / d;
852-
(*t_combiner) -> x_inc = (uint4) (STOP_INT_MAX * (int64_t)((*t_combiner) -> origin . x * wy + ((int64_t) r_clip . origin .y - (*t_combiner) -> origin . y) * wx) / d);
696+
(*t_combiner) -> x_inc = (uint4) (STOP_INT_MAX * (int64_t)((*t_combiner) -> origin . x * wy + ((int64_t) p_clip . origin .y - (*t_combiner) -> origin . y) * wx) / d);
853697

854698
(*t_combiner) -> y_coef_a = STOP_INT_MAX * vy / d;
855699
(*t_combiner) -> y_coef_b = STOP_INT_MAX * -vx / d;
856-
(*t_combiner) -> y_inc = (uint4) (STOP_INT_MAX * -(int64_t)((*t_combiner) -> origin . x * vy + ((int64_t) r_clip . origin .y - (*t_combiner) -> origin . y) * vx) / d);
700+
(*t_combiner) -> y_inc = (uint4) (STOP_INT_MAX * -(int64_t)((*t_combiner) -> origin . x * vy + ((int64_t) p_clip . origin .y - (*t_combiner) -> origin . y) * vx) / d);
857701
}
858702

859703
// MM-2014-01-27: [[ UpdateImageFilters ]] Updated to use new libgraphics image filter types.
@@ -895,8 +739,7 @@ MCGradientAffineCombiner *MCGradientFillCreateCombiner(MCGGradientRef p_gradient
895739
case kMCGImageFilterMedium:
896740
case kMCGImageFilterHigh:
897741
{
898-
(*t_combiner) -> end = gradient_bilinear_affine_combiner_end;
899-
(*t_combiner) -> buffer_width = GRADIENT_AA_SCALE * (uint32_t) ceilf(r_clip . size . width);
742+
(*t_combiner) -> buffer_width = GRADIENT_AA_SCALE * (uint32_t) ceilf(p_clip . size . width);
900743

901744
if (!MCMemoryNewArray(GRADIENT_AA_SCALE * (*t_combiner) -> buffer_width, (*t_combiner) -> buffer))
902745
return nil;
@@ -955,7 +798,7 @@ size_t MCGLegacyGradientShader::onContextSize(const ContextRec&) const
955798

956799
SkShader::Context* MCGLegacyGradientShader::onCreateContext(const ContextRec& p_rec, void* p_storage) const
957800
{
958-
return new (nothrow) MCGLegacyGradientShaderContext(*this, p_rec, m_gradient_ref, m_clip);
801+
return new (p_storage) MCGLegacyGradientShaderContext(*this, p_rec, m_gradient_ref, m_clip);
959802
}
960803

961804
#ifndef SK_IGNORE_TO_STRING
@@ -971,7 +814,7 @@ sk_sp<SkFlattenable> MCGLegacyGradientShader::CreateProc(SkReadBuffer& buffer)
971814
}
972815

973816
MCGLegacyGradientShader::MCGLegacyGradientShaderContext::MCGLegacyGradientShaderContext(const MCGLegacyGradientShader& p_shader, const ContextRec& p_rec, MCGGradientRef p_gradient_ref, MCGRectangle p_clip)
974-
: INHERITED(p_shader, p_rec), m_y(0), m_mask(NULL), m_gradient_combiner(NULL)
817+
: INHERITED(p_shader, p_rec), m_y(0), m_gradient_combiner(NULL)
975818
{
976819
MCGRectangle t_clip;
977820

@@ -985,12 +828,8 @@ MCGLegacyGradientShader::MCGLegacyGradientShaderContext::MCGLegacyGradientShader
985828
bool t_success;
986829
t_success = true;
987830

988-
if (t_success)
989-
t_success = MCMemoryAllocate(t_width, m_mask);
990-
991831
if (t_success)
992832
{
993-
memset(m_mask, 0xFF, t_width);
994833
m_gradient_combiner = MCGradientFillCreateCombiner(p_gradient_ref, t_clip, t_matrix);
995834
t_success = m_gradient_combiner != NULL;
996835
}
@@ -1006,7 +845,6 @@ MCGLegacyGradientShader::MCGLegacyGradientShaderContext::MCGLegacyGradientShader
1006845

1007846
MCGLegacyGradientShader::MCGLegacyGradientShaderContext::~MCGLegacyGradientShaderContext()
1008847
{
1009-
MCMemoryDeallocate(m_mask);
1010848
MCGradientFillDeleteCombiner(m_gradient_combiner);
1011849
}
1012850

@@ -1020,7 +858,7 @@ void MCGLegacyGradientShader::MCGLegacyGradientShaderContext::shadeSpan(int x, i
1020858
m_y = y;
1021859
memset(dstC, 0x00, count * sizeof(SkPMColor));
1022860
m_gradient_combiner -> bits = dstC - x;
1023-
m_gradient_combiner -> combine(m_gradient_combiner, x, x + count, m_mask);
861+
m_gradient_combiner -> combine(m_gradient_combiner, x, x + count);
1024862
}
1025863
}
1026864

0 commit comments

Comments
 (0)