@@ -1042,130 +1042,99 @@ font_render(FontObject *self, PyObject *args) {
10421042 yy = - (py + glyph_slot -> bitmap_top );
10431043 }
10441044
1045- // Null buffer, is dereferenced in FT_Bitmap_Convert
1046- if (!bitmap .buffer && bitmap .rows ) {
1047- PyErr_SetString (PyExc_OSError , "Bitmap missing for glyph" );
1048- goto glyph_error ;
1049- }
1050-
1051- /* convert non-8bpp bitmaps */
1052- switch (bitmap .pixel_mode ) {
1053- case FT_PIXEL_MODE_MONO :
1054- convert_scale = 255 ;
1055- break ;
1056- case FT_PIXEL_MODE_GRAY2 :
1057- convert_scale = 255 / 3 ;
1058- break ;
1059- case FT_PIXEL_MODE_GRAY4 :
1060- convert_scale = 255 / 15 ;
1061- break ;
1062- default :
1063- convert_scale = 1 ;
1064- }
1065- switch (bitmap .pixel_mode ) {
1066- case FT_PIXEL_MODE_MONO :
1067- case FT_PIXEL_MODE_GRAY2 :
1068- case FT_PIXEL_MODE_GRAY4 :
1069- if (!bitmap_converted_ready ) {
1070- FT_Bitmap_Init (& bitmap_converted );
1071- bitmap_converted_ready = 1 ;
1072- }
1073- error = FT_Bitmap_Convert (library , & bitmap , & bitmap_converted , 1 );
1074- if (error ) {
1075- geterror (error );
1076- goto glyph_error ;
1077- }
1078- bitmap = bitmap_converted ;
1079- /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
1080- case FT_PIXEL_MODE_GRAY :
1081- break ;
1082- case FT_PIXEL_MODE_BGRA :
1083- if (color ) {
1045+ if (bitmap .buffer ) {
1046+ /* convert non-8bpp bitmaps */
1047+ switch (bitmap .pixel_mode ) {
1048+ case FT_PIXEL_MODE_MONO :
1049+ convert_scale = 255 ;
10841050 break ;
1085- }
1086- /* we didn't ask for color, fall through to default */
1087- default :
1088- PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1089- goto glyph_error ;
1090- }
1051+ case FT_PIXEL_MODE_GRAY2 :
1052+ convert_scale = 255 / 3 ;
1053+ break ;
1054+ case FT_PIXEL_MODE_GRAY4 :
1055+ convert_scale = 255 / 15 ;
1056+ break ;
1057+ default :
1058+ convert_scale = 1 ;
1059+ }
1060+ switch (bitmap .pixel_mode ) {
1061+ case FT_PIXEL_MODE_MONO :
1062+ case FT_PIXEL_MODE_GRAY2 :
1063+ case FT_PIXEL_MODE_GRAY4 :
1064+ if (!bitmap_converted_ready ) {
1065+ FT_Bitmap_Init (& bitmap_converted );
1066+ bitmap_converted_ready = 1 ;
1067+ }
1068+ error = FT_Bitmap_Convert (library , & bitmap , & bitmap_converted , 1 );
1069+ if (error ) {
1070+ geterror (error );
1071+ goto glyph_error ;
1072+ }
1073+ bitmap = bitmap_converted ;
1074+ /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
1075+ case FT_PIXEL_MODE_GRAY :
1076+ break ;
1077+ case FT_PIXEL_MODE_BGRA :
1078+ if (color ) {
1079+ break ;
1080+ }
1081+ /* we didn't ask for color, fall through to default */
1082+ default :
1083+ PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1084+ goto glyph_error ;
1085+ }
10911086
1092- /* clip glyph bitmap width to target image bounds */
1093- x0 = 0 ;
1094- x1 = bitmap .width ;
1095- if (xx < 0 ) {
1096- x0 = - xx ;
1097- }
1098- if (xx + x1 > im -> xsize ) {
1099- x1 = im -> xsize - xx ;
1100- }
1087+ /* clip glyph bitmap width to target image bounds */
1088+ x0 = 0 ;
1089+ x1 = bitmap .width ;
1090+ if (xx < 0 ) {
1091+ x0 = - xx ;
1092+ }
1093+ if (xx + x1 > im -> xsize ) {
1094+ x1 = im -> xsize - xx ;
1095+ }
11011096
1102- source = (unsigned char * )bitmap .buffer ;
1103- for (bitmap_y = 0 ; bitmap_y < bitmap .rows ; bitmap_y ++ , yy ++ ) {
1104- /* clip glyph bitmap height to target image bounds */
1105- if (yy >= 0 && yy < im -> ysize ) {
1106- /* blend this glyph into the buffer */
1107- int k ;
1108- unsigned char * target ;
1109- unsigned int tmp ;
1110- if (color ) {
1111- /* target[RGB] returns the color, target[A] returns the mask */
1112- /* target bands get split again in ImageDraw.text */
1113- target = (unsigned char * )im -> image [yy ] + xx * 4 ;
1114- } else {
1115- target = im -> image8 [yy ] + xx ;
1116- }
1117- if (color && bitmap .pixel_mode == FT_PIXEL_MODE_BGRA ) {
1118- /* paste color glyph */
1119- for (k = x0 ; k < x1 ; k ++ ) {
1120- unsigned int src_alpha = source [k * 4 + 3 ];
1121-
1122- /* paste only if source has data */
1123- if (src_alpha > 0 ) {
1124- /* unpremultiply BGRa */
1125- int src_red =
1126- CLIP8 ((255 * (int )source [k * 4 + 2 ]) / src_alpha );
1127- int src_green =
1128- CLIP8 ((255 * (int )source [k * 4 + 1 ]) / src_alpha );
1129- int src_blue =
1130- CLIP8 ((255 * (int )source [k * 4 + 0 ]) / src_alpha );
1131-
1132- /* blend required if target has data */
1133- if (target [k * 4 + 3 ] > 0 ) {
1134- /* blend RGBA colors */
1135- target [k * 4 + 0 ] =
1136- BLEND (src_alpha , target [k * 4 + 0 ], src_red , tmp );
1137- target [k * 4 + 1 ] =
1138- BLEND (src_alpha , target [k * 4 + 1 ], src_green , tmp );
1139- target [k * 4 + 2 ] =
1140- BLEND (src_alpha , target [k * 4 + 2 ], src_blue , tmp );
1141- target [k * 4 + 3 ] = CLIP8 (
1142- src_alpha +
1143- MULDIV255 (target [k * 4 + 3 ], (255 - src_alpha ), tmp )
1144- );
1145- } else {
1146- /* paste unpremultiplied RGBA values */
1147- target [k * 4 + 0 ] = src_red ;
1148- target [k * 4 + 1 ] = src_green ;
1149- target [k * 4 + 2 ] = src_blue ;
1150- target [k * 4 + 3 ] = src_alpha ;
1151- }
1152- }
1153- }
1154- } else if (bitmap .pixel_mode == FT_PIXEL_MODE_GRAY ) {
1097+ source = (unsigned char * )bitmap .buffer ;
1098+ for (bitmap_y = 0 ; bitmap_y < bitmap .rows ; bitmap_y ++ , yy ++ ) {
1099+ /* clip glyph bitmap height to target image bounds */
1100+ if (yy >= 0 && yy < im -> ysize ) {
1101+ /* blend this glyph into the buffer */
1102+ int k ;
1103+ unsigned char * target ;
1104+ unsigned int tmp ;
11551105 if (color ) {
1156- unsigned char * ink = (unsigned char * )& foreground_ink ;
1106+ /* target[RGB] returns the color, target[A] returns the mask */
1107+ /* target bands get split again in ImageDraw.text */
1108+ target = (unsigned char * )im -> image [yy ] + xx * 4 ;
1109+ } else {
1110+ target = im -> image8 [yy ] + xx ;
1111+ }
1112+ if (color && bitmap .pixel_mode == FT_PIXEL_MODE_BGRA ) {
1113+ /* paste color glyph */
11571114 for (k = x0 ; k < x1 ; k ++ ) {
1158- unsigned int src_alpha = source [k ] * convert_scale ;
1115+ unsigned int src_alpha = source [k * 4 + 3 ];
1116+
1117+ /* paste only if source has data */
11591118 if (src_alpha > 0 ) {
1119+ /* unpremultiply BGRa */
1120+ int src_red =
1121+ CLIP8 ((255 * (int )source [k * 4 + 2 ]) / src_alpha );
1122+ int src_green =
1123+ CLIP8 ((255 * (int )source [k * 4 + 1 ]) / src_alpha );
1124+ int src_blue =
1125+ CLIP8 ((255 * (int )source [k * 4 + 0 ]) / src_alpha );
1126+
1127+ /* blend required if target has data */
11601128 if (target [k * 4 + 3 ] > 0 ) {
1129+ /* blend RGBA colors */
11611130 target [k * 4 + 0 ] = BLEND (
1162- src_alpha , target [k * 4 + 0 ], ink [ 0 ] , tmp
1131+ src_alpha , target [k * 4 + 0 ], src_red , tmp
11631132 );
11641133 target [k * 4 + 1 ] = BLEND (
1165- src_alpha , target [k * 4 + 1 ], ink [ 1 ] , tmp
1134+ src_alpha , target [k * 4 + 1 ], src_green , tmp
11661135 );
11671136 target [k * 4 + 2 ] = BLEND (
1168- src_alpha , target [k * 4 + 2 ], ink [ 2 ] , tmp
1137+ src_alpha , target [k * 4 + 2 ], src_blue , tmp
11691138 );
11701139 target [k * 4 + 3 ] = CLIP8 (
11711140 src_alpha +
@@ -1174,35 +1143,68 @@ font_render(FontObject *self, PyObject *args) {
11741143 )
11751144 );
11761145 } else {
1177- target [k * 4 + 0 ] = ink [0 ];
1178- target [k * 4 + 1 ] = ink [1 ];
1179- target [k * 4 + 2 ] = ink [2 ];
1146+ /* paste unpremultiplied RGBA values */
1147+ target [k * 4 + 0 ] = src_red ;
1148+ target [k * 4 + 1 ] = src_green ;
1149+ target [k * 4 + 2 ] = src_blue ;
11801150 target [k * 4 + 3 ] = src_alpha ;
11811151 }
11821152 }
11831153 }
1184- } else {
1185- for (k = x0 ; k < x1 ; k ++ ) {
1186- unsigned int src_alpha = source [k ] * convert_scale ;
1187- if (src_alpha > 0 ) {
1188- target [k ] =
1189- target [k ] > 0
1190- ? CLIP8 (
1191- src_alpha +
1192- MULDIV255 (
1193- target [k ], (255 - src_alpha ), tmp
1154+ } else if (bitmap .pixel_mode == FT_PIXEL_MODE_GRAY ) {
1155+ if (color ) {
1156+ unsigned char * ink = (unsigned char * )& foreground_ink ;
1157+ for (k = x0 ; k < x1 ; k ++ ) {
1158+ unsigned int src_alpha = source [k ] * convert_scale ;
1159+ if (src_alpha > 0 ) {
1160+ if (target [k * 4 + 3 ] > 0 ) {
1161+ target [k * 4 + 0 ] = BLEND (
1162+ src_alpha , target [k * 4 + 0 ], ink [0 ], tmp
1163+ );
1164+ target [k * 4 + 1 ] = BLEND (
1165+ src_alpha , target [k * 4 + 1 ], ink [1 ], tmp
1166+ );
1167+ target [k * 4 + 2 ] = BLEND (
1168+ src_alpha , target [k * 4 + 2 ], ink [2 ], tmp
1169+ );
1170+ target [k * 4 + 3 ] = CLIP8 (
1171+ src_alpha + MULDIV255 (
1172+ target [k * 4 + 3 ],
1173+ (255 - src_alpha ),
1174+ tmp
1175+ )
1176+ );
1177+ } else {
1178+ target [k * 4 + 0 ] = ink [0 ];
1179+ target [k * 4 + 1 ] = ink [1 ];
1180+ target [k * 4 + 2 ] = ink [2 ];
1181+ target [k * 4 + 3 ] = src_alpha ;
1182+ }
1183+ }
1184+ }
1185+ } else {
1186+ for (k = x0 ; k < x1 ; k ++ ) {
1187+ unsigned int src_alpha = source [k ] * convert_scale ;
1188+ if (src_alpha > 0 ) {
1189+ target [k ] =
1190+ target [k ] > 0
1191+ ? CLIP8 (
1192+ src_alpha +
1193+ MULDIV255 (
1194+ target [k ], (255 - src_alpha ), tmp
1195+ )
11941196 )
1195- )
1196- : src_alpha ;
1197+ : src_alpha ;
1198+ }
11971199 }
11981200 }
1201+ } else {
1202+ PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1203+ goto glyph_error ;
11991204 }
1200- } else {
1201- PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1202- goto glyph_error ;
12031205 }
1206+ source += bitmap .pitch ;
12041207 }
1205- source += bitmap .pitch ;
12061208 }
12071209 x += glyph_info [i ].x_advance ;
12081210 y += glyph_info [i ].y_advance ;
0 commit comments