Skip to content

Commit dabf47c

Browse files
committed
Refactor tiled texture blending to apply bilinear sampling only for rotation and shear
1 parent 9476fae commit dabf47c

File tree

1 file changed

+60
-1
lines changed

1 file changed

+60
-1
lines changed

source/plutovg-blend.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,63 @@ static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_o
866866
}
867867
}
868868

869+
static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const texture_data_t* texture, const plutovg_span_buffer_t* span_buffer)
870+
{
871+
composition_function_t func = composition_table[op];
872+
uint32_t buffer[BUFFER_SIZE];
873+
874+
int image_width = texture->width;
875+
int image_height = texture->height;
876+
const int scanline_offset = texture->stride / 4;
877+
878+
int fdx = (int)(texture->matrix.a * FIXED_SCALE);
879+
int fdy = (int)(texture->matrix.b * FIXED_SCALE);
880+
881+
int count = span_buffer->spans.size;
882+
const plutovg_span_t* spans = span_buffer->spans.data;
883+
while(count--) {
884+
uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + spans->x;
885+
const uint32_t* image_bits = (const uint32_t*)texture->data;
886+
887+
const float cx = spans->x + 0.5f;
888+
const float cy = spans->y + 0.5f;
889+
890+
int x = (int)((texture->matrix.c * cy + texture->matrix.a * cx + texture->matrix.e) * FIXED_SCALE);
891+
int y = (int)((texture->matrix.d * cy + texture->matrix.b * cx + texture->matrix.f) * FIXED_SCALE);
892+
893+
const int coverage = (spans->coverage * texture->const_alpha) >> 8;
894+
int length = spans->len;
895+
while(length) {
896+
int l = plutovg_min(length, BUFFER_SIZE);
897+
const uint32_t* end = buffer + l;
898+
uint32_t* b = buffer;
899+
while(b < end) {
900+
int px = x >> 16;
901+
int py = y >> 16;
902+
px %= image_width;
903+
py %= image_height;
904+
if(px < 0) px += image_width;
905+
if(py < 0) py += image_height;
906+
int y_offset = py * scanline_offset;
907+
908+
assert(px >= 0 && px < image_width);
909+
assert(py >= 0 && py < image_height);
910+
911+
*b = image_bits[y_offset + px];
912+
x += fdx;
913+
y += fdy;
914+
++b;
915+
}
916+
917+
func(target, l, buffer, coverage);
918+
target += l;
919+
length -= l;
920+
}
921+
922+
++spans;
923+
}
924+
}
925+
869926
static inline uint32_t interpolate_4_pixels(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br, uint32_t distx, uint32_t disty)
870927
{
871928
uint32_t idistx = 256 - distx;
@@ -876,7 +933,7 @@ static inline uint32_t interpolate_4_pixels(uint32_t tl, uint32_t tr, uint32_t b
876933
}
877934

878935
#define HALF_POINT (1 << 15)
879-
static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const texture_data_t* texture, const plutovg_span_buffer_t* span_buffer)
936+
static void blend_transformed_bilinear_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const texture_data_t* texture, const plutovg_span_buffer_t* span_buffer)
880937
{
881938
composition_function_t func = composition_table[op];
882939
uint32_t buffer[BUFFER_SIZE];
@@ -1056,6 +1113,8 @@ static void plutovg_blend_texture(plutovg_canvas_t* canvas, const plutovg_textur
10561113
} else {
10571114
if(texture->type == PLUTOVG_TEXTURE_TYPE_PLAIN) {
10581115
blend_transformed_argb(canvas->surface, state->op, &data, span_buffer);
1116+
} else if(fabsf(matrix->b) > 1e-6f || fabsf(matrix->c) > 1e-6f) {
1117+
blend_transformed_bilinear_tiled_argb(canvas->surface, state->op, &data, span_buffer);
10591118
} else {
10601119
blend_transformed_tiled_argb(canvas->surface, state->op, &data, span_buffer);
10611120
}

0 commit comments

Comments
 (0)