@@ -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+
869926static 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