@@ -63,7 +63,7 @@ typedef struct {
6363} Edge ;
6464
6565/* Type used in "polygon*" functions */
66- typedef void (* hline_handler )(Imaging , int , int , int , int );
66+ typedef void (* hline_handler )(Imaging , int , int , int , int , Imaging );
6767
6868static inline void
6969point8 (Imaging im , int x , int y , int ink ) {
@@ -103,7 +103,7 @@ point32rgba(Imaging im, int x, int y, int ink) {
103103}
104104
105105static inline void
106- hline8 (Imaging im , int x0 , int y0 , int x1 , int ink ) {
106+ hline8 (Imaging im , int x0 , int y0 , int x1 , int ink , Imaging mask ) {
107107 int pixelwidth ;
108108
109109 if (y0 >= 0 && y0 < im -> ysize ) {
@@ -119,15 +119,30 @@ hline8(Imaging im, int x0, int y0, int x1, int ink) {
119119 }
120120 if (x0 <= x1 ) {
121121 pixelwidth = strncmp (im -> mode , "I;16" , 4 ) == 0 ? 2 : 1 ;
122- memset (
123- im -> image8 [y0 ] + x0 * pixelwidth , (UINT8 )ink , (x1 - x0 + 1 ) * pixelwidth
124- );
122+ if (mask == NULL ) {
123+ memset (
124+ im -> image8 [y0 ] + x0 * pixelwidth ,
125+ (UINT8 )ink ,
126+ (x1 - x0 + 1 ) * pixelwidth
127+ );
128+ } else {
129+ UINT8 * p = im -> image8 [y0 ];
130+ while (x0 <= x1 ) {
131+ if (mask -> image8 [y0 ][x0 ]) {
132+ p [x0 * pixelwidth ] = ink ;
133+ if (pixelwidth == 2 ) {
134+ p [x0 * pixelwidth + 1 ] = ink ;
135+ }
136+ }
137+ x0 ++ ;
138+ }
139+ }
125140 }
126141 }
127142}
128143
129144static inline void
130- hline32 (Imaging im , int x0 , int y0 , int x1 , int ink ) {
145+ hline32 (Imaging im , int x0 , int y0 , int x1 , int ink , Imaging mask ) {
131146 INT32 * p ;
132147
133148 if (y0 >= 0 && y0 < im -> ysize ) {
@@ -143,13 +158,16 @@ hline32(Imaging im, int x0, int y0, int x1, int ink) {
143158 }
144159 p = im -> image32 [y0 ];
145160 while (x0 <= x1 ) {
146- p [x0 ++ ] = ink ;
161+ if (mask == NULL || mask -> image8 [y0 ][x0 ]) {
162+ p [x0 ] = ink ;
163+ }
164+ x0 ++ ;
147165 }
148166 }
149167}
150168
151169static inline void
152- hline32rgba (Imaging im , int x0 , int y0 , int x1 , int ink ) {
170+ hline32rgba (Imaging im , int x0 , int y0 , int x1 , int ink , Imaging mask ) {
153171 unsigned int tmp ;
154172
155173 if (y0 >= 0 && y0 < im -> ysize ) {
@@ -167,9 +185,11 @@ hline32rgba(Imaging im, int x0, int y0, int x1, int ink) {
167185 UINT8 * out = (UINT8 * )im -> image [y0 ] + x0 * 4 ;
168186 UINT8 * in = (UINT8 * )& ink ;
169187 while (x0 <= x1 ) {
170- out [0 ] = BLEND (in [3 ], out [0 ], in [0 ], tmp );
171- out [1 ] = BLEND (in [3 ], out [1 ], in [1 ], tmp );
172- out [2 ] = BLEND (in [3 ], out [2 ], in [2 ], tmp );
188+ if (mask == NULL || mask -> image8 [y0 ][x0 ]) {
189+ out [0 ] = BLEND (in [3 ], out [0 ], in [0 ], tmp );
190+ out [1 ] = BLEND (in [3 ], out [1 ], in [1 ], tmp );
191+ out [2 ] = BLEND (in [3 ], out [2 ], in [2 ], tmp );
192+ }
173193 x0 ++ ;
174194 out += 4 ;
175195 }
@@ -407,7 +427,14 @@ x_cmp(const void *x0, const void *x1) {
407427
408428static void
409429draw_horizontal_lines (
410- Imaging im , int n , Edge * e , int ink , int * x_pos , int y , hline_handler hline
430+ Imaging im ,
431+ int n ,
432+ Edge * e ,
433+ int ink ,
434+ int * x_pos ,
435+ int y ,
436+ hline_handler hline ,
437+ Imaging mask
411438) {
412439 int i ;
413440 for (i = 0 ; i < n ; i ++ ) {
@@ -429,7 +456,7 @@ draw_horizontal_lines(
429456 }
430457 }
431458
432- (* hline )(im , xmin , e [i ].ymin , xmax , ink );
459+ (* hline )(im , xmin , e [i ].ymin , xmax , ink , mask );
433460 * x_pos = xmax + 1 ;
434461 }
435462 }
@@ -439,7 +466,9 @@ draw_horizontal_lines(
439466 * Filled polygon draw function using scan line algorithm.
440467 */
441468static inline int
442- polygon_generic (Imaging im , int n , Edge * e , int ink , int eofill , hline_handler hline ) {
469+ polygon_generic (
470+ Imaging im , int n , Edge * e , int ink , int eofill , hline_handler hline , Imaging mask
471+ ) {
443472 Edge * * edge_table ;
444473 float * xx ;
445474 int edge_count = 0 ;
@@ -469,7 +498,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
469498 }
470499 if (e [i ].ymin == e [i ].ymax ) {
471500 if (hasAlpha != 1 ) {
472- (* hline )(im , e [i ].xmin , e [i ].ymin , e [i ].xmax , ink );
501+ (* hline )(im , e [i ].xmin , e [i ].ymin , e [i ].xmax , ink , mask );
473502 }
474503 continue ;
475504 }
@@ -557,7 +586,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
557586 // Line would be before the current position
558587 continue ;
559588 }
560- draw_horizontal_lines (im , n , e , ink , & x_pos , ymin , hline );
589+ draw_horizontal_lines (im , n , e , ink , & x_pos , ymin , hline , mask );
561590 if (x_end < x_pos ) {
562591 // Line would be before the current position
563592 continue ;
@@ -573,13 +602,13 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
573602 continue ;
574603 }
575604 }
576- (* hline )(im , x_start , ymin , x_end , ink );
605+ (* hline )(im , x_start , ymin , x_end , ink , mask );
577606 x_pos = x_end + 1 ;
578607 }
579- draw_horizontal_lines (im , n , e , ink , & x_pos , ymin , hline );
608+ draw_horizontal_lines (im , n , e , ink , & x_pos , ymin , hline , mask );
580609 } else {
581610 for (i = 1 ; i < j ; i += 2 ) {
582- (* hline )(im , ROUND_UP (xx [i - 1 ]), ymin , ROUND_DOWN (xx [i ]), ink );
611+ (* hline )(im , ROUND_UP (xx [i - 1 ]), ymin , ROUND_DOWN (xx [i ]), ink , mask );
583612 }
584613 }
585614 }
@@ -623,7 +652,7 @@ add_edge(Edge *e, int x0, int y0, int x1, int y1) {
623652
624653typedef struct {
625654 void (* point )(Imaging im , int x , int y , int ink );
626- void (* hline )(Imaging im , int x0 , int y0 , int x1 , int ink );
655+ void (* hline )(Imaging im , int x0 , int y0 , int x1 , int ink , Imaging mask );
627656 void (* line )(Imaging im , int x0 , int y0 , int x1 , int y1 , int ink );
628657} DRAW ;
629658
@@ -674,7 +703,15 @@ ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void *ink_, in
674703
675704int
676705ImagingDrawWideLine (
677- Imaging im , int x0 , int y0 , int x1 , int y1 , const void * ink_ , int width , int op
706+ Imaging im ,
707+ int x0 ,
708+ int y0 ,
709+ int x1 ,
710+ int y1 ,
711+ const void * ink_ ,
712+ int width ,
713+ int op ,
714+ Imaging mask
678715) {
679716 DRAW * draw ;
680717 INT32 ink ;
@@ -714,7 +751,7 @@ ImagingDrawWideLine(
714751 add_edge (e + 2 , vertices [2 ][0 ], vertices [2 ][1 ], vertices [3 ][0 ], vertices [3 ][1 ]);
715752 add_edge (e + 3 , vertices [3 ][0 ], vertices [3 ][1 ], vertices [0 ][0 ], vertices [0 ][1 ]);
716753
717- polygon_generic (im , 4 , e , ink , 0 , draw -> hline );
754+ polygon_generic (im , 4 , e , ink , 0 , draw -> hline , mask );
718755 }
719756 return 0 ;
720757}
@@ -757,7 +794,7 @@ ImagingDrawRectangle(
757794 }
758795
759796 for (y = y0 ; y <= y1 ; y ++ ) {
760- draw -> hline (im , x0 , y , x1 , ink );
797+ draw -> hline (im , x0 , y , x1 , ink , NULL );
761798 }
762799
763800 } else {
@@ -766,8 +803,8 @@ ImagingDrawRectangle(
766803 width = 1 ;
767804 }
768805 for (i = 0 ; i < width ; i ++ ) {
769- draw -> hline (im , x0 , y0 + i , x1 , ink );
770- draw -> hline (im , x0 , y1 - i , x1 , ink );
806+ draw -> hline (im , x0 , y0 + i , x1 , ink , NULL );
807+ draw -> hline (im , x0 , y1 - i , x1 , ink , NULL );
771808 draw -> line (im , x1 - i , y0 + width , x1 - i , y1 - width + 1 , ink );
772809 draw -> line (im , x0 + i , y0 + width , x0 + i , y1 - width + 1 , ink );
773810 }
@@ -778,7 +815,14 @@ ImagingDrawRectangle(
778815
779816int
780817ImagingDrawPolygon (
781- Imaging im , int count , int * xy , const void * ink_ , int fill , int width , int op
818+ Imaging im ,
819+ int count ,
820+ int * xy ,
821+ const void * ink_ ,
822+ int fill ,
823+ int width ,
824+ int op ,
825+ Imaging mask
782826) {
783827 int i , n , x0 , y0 , x1 , y1 ;
784828 DRAW * draw ;
@@ -822,7 +866,7 @@ ImagingDrawPolygon(
822866 if (xy [i * 2 ] != xy [0 ] || xy [i * 2 + 1 ] != xy [1 ]) {
823867 add_edge (& e [n ++ ], xy [i * 2 ], xy [i * 2 + 1 ], xy [0 ], xy [1 ]);
824868 }
825- polygon_generic (im , n , e , ink , 0 , draw -> hline );
869+ polygon_generic (im , n , e , ink , 0 , draw -> hline , mask );
826870 free (e );
827871
828872 } else {
@@ -844,11 +888,12 @@ ImagingDrawPolygon(
844888 xy [i * 2 + 3 ],
845889 ink_ ,
846890 width ,
847- op
891+ op ,
892+ mask
848893 );
849894 }
850895 ImagingDrawWideLine (
851- im , xy [i * 2 ], xy [i * 2 + 1 ], xy [0 ], xy [1 ], ink_ , width , op
896+ im , xy [i * 2 ], xy [i * 2 + 1 ], xy [0 ], xy [1 ], ink_ , width , op , mask
852897 );
853898 }
854899 }
@@ -1519,7 +1564,9 @@ ellipseNew(
15191564 ellipse_init (& st , a , b , width );
15201565 int32_t X0 , Y , X1 ;
15211566 while (ellipse_next (& st , & X0 , & Y , & X1 ) != -1 ) {
1522- draw -> hline (im , x0 + (X0 + a ) / 2 , y0 + (Y + b ) / 2 , x0 + (X1 + a ) / 2 , ink );
1567+ draw -> hline (
1568+ im , x0 + (X0 + a ) / 2 , y0 + (Y + b ) / 2 , x0 + (X1 + a ) / 2 , ink , NULL
1569+ );
15231570 }
15241571 return 0 ;
15251572}
@@ -1554,7 +1601,9 @@ clipEllipseNew(
15541601 int32_t X0 , Y , X1 ;
15551602 int next_code ;
15561603 while ((next_code = clip_ellipse_next (& st , & X0 , & Y , & X1 )) >= 0 ) {
1557- draw -> hline (im , x0 + (X0 + a ) / 2 , y0 + (Y + b ) / 2 , x0 + (X1 + a ) / 2 , ink );
1604+ draw -> hline (
1605+ im , x0 + (X0 + a ) / 2 , y0 + (Y + b ) / 2 , x0 + (X1 + a ) / 2 , ink , NULL
1606+ );
15581607 }
15591608 clip_ellipse_free (& st );
15601609 return next_code == -1 ? 0 : -1 ;
@@ -1972,7 +2021,7 @@ ImagingDrawOutline(
19722021
19732022 DRAWINIT ();
19742023
1975- polygon_generic (im , outline -> count , outline -> edges , ink , 0 , draw -> hline );
2024+ polygon_generic (im , outline -> count , outline -> edges , ink , 0 , draw -> hline , NULL );
19762025
19772026 return 0 ;
19782027}
0 commit comments