@@ -1025,130 +1025,99 @@ font_render(FontObject *self, PyObject *args) {
10251025 yy = - (py + glyph_slot -> bitmap_top );
10261026 }
10271027
1028- // Null buffer, is dereferenced in FT_Bitmap_Convert
1029- if (!bitmap .buffer && bitmap .rows ) {
1030- PyErr_SetString (PyExc_OSError , "Bitmap missing for glyph" );
1031- goto glyph_error ;
1032- }
1033-
1034- /* convert non-8bpp bitmaps */
1035- switch (bitmap .pixel_mode ) {
1036- case FT_PIXEL_MODE_MONO :
1037- convert_scale = 255 ;
1038- break ;
1039- case FT_PIXEL_MODE_GRAY2 :
1040- convert_scale = 255 / 3 ;
1041- break ;
1042- case FT_PIXEL_MODE_GRAY4 :
1043- convert_scale = 255 / 15 ;
1044- break ;
1045- default :
1046- convert_scale = 1 ;
1047- }
1048- switch (bitmap .pixel_mode ) {
1049- case FT_PIXEL_MODE_MONO :
1050- case FT_PIXEL_MODE_GRAY2 :
1051- case FT_PIXEL_MODE_GRAY4 :
1052- if (!bitmap_converted_ready ) {
1053- FT_Bitmap_Init (& bitmap_converted );
1054- bitmap_converted_ready = 1 ;
1055- }
1056- error = FT_Bitmap_Convert (library , & bitmap , & bitmap_converted , 1 );
1057- if (error ) {
1058- geterror (error );
1059- goto glyph_error ;
1060- }
1061- bitmap = bitmap_converted ;
1062- /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
1063- case FT_PIXEL_MODE_GRAY :
1064- break ;
1065- case FT_PIXEL_MODE_BGRA :
1066- if (color ) {
1028+ if (bitmap .buffer ) {
1029+ /* convert non-8bpp bitmaps */
1030+ switch (bitmap .pixel_mode ) {
1031+ case FT_PIXEL_MODE_MONO :
1032+ convert_scale = 255 ;
10671033 break ;
1068- }
1069- /* we didn't ask for color, fall through to default */
1070- default :
1071- PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1072- goto glyph_error ;
1073- }
1034+ case FT_PIXEL_MODE_GRAY2 :
1035+ convert_scale = 255 / 3 ;
1036+ break ;
1037+ case FT_PIXEL_MODE_GRAY4 :
1038+ convert_scale = 255 / 15 ;
1039+ break ;
1040+ default :
1041+ convert_scale = 1 ;
1042+ }
1043+ switch (bitmap .pixel_mode ) {
1044+ case FT_PIXEL_MODE_MONO :
1045+ case FT_PIXEL_MODE_GRAY2 :
1046+ case FT_PIXEL_MODE_GRAY4 :
1047+ if (!bitmap_converted_ready ) {
1048+ FT_Bitmap_Init (& bitmap_converted );
1049+ bitmap_converted_ready = 1 ;
1050+ }
1051+ error = FT_Bitmap_Convert (library , & bitmap , & bitmap_converted , 1 );
1052+ if (error ) {
1053+ geterror (error );
1054+ goto glyph_error ;
1055+ }
1056+ bitmap = bitmap_converted ;
1057+ /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
1058+ case FT_PIXEL_MODE_GRAY :
1059+ break ;
1060+ case FT_PIXEL_MODE_BGRA :
1061+ if (color ) {
1062+ break ;
1063+ }
1064+ /* we didn't ask for color, fall through to default */
1065+ default :
1066+ PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1067+ goto glyph_error ;
1068+ }
10741069
1075- /* clip glyph bitmap width to target image bounds */
1076- x0 = 0 ;
1077- x1 = bitmap .width ;
1078- if (xx < 0 ) {
1079- x0 = - xx ;
1080- }
1081- if (xx + x1 > im -> xsize ) {
1082- x1 = im -> xsize - xx ;
1083- }
1070+ /* clip glyph bitmap width to target image bounds */
1071+ x0 = 0 ;
1072+ x1 = bitmap .width ;
1073+ if (xx < 0 ) {
1074+ x0 = - xx ;
1075+ }
1076+ if (xx + x1 > im -> xsize ) {
1077+ x1 = im -> xsize - xx ;
1078+ }
10841079
1085- source = (unsigned char * )bitmap .buffer ;
1086- for (bitmap_y = 0 ; bitmap_y < bitmap .rows ; bitmap_y ++ , yy ++ ) {
1087- /* clip glyph bitmap height to target image bounds */
1088- if (yy >= 0 && yy < im -> ysize ) {
1089- /* blend this glyph into the buffer */
1090- int k ;
1091- unsigned char * target ;
1092- unsigned int tmp ;
1093- if (color ) {
1094- /* target[RGB] returns the color, target[A] returns the mask */
1095- /* target bands get split again in ImageDraw.text */
1096- target = (unsigned char * )im -> image [yy ] + xx * 4 ;
1097- } else {
1098- target = im -> image8 [yy ] + xx ;
1099- }
1100- if (color && bitmap .pixel_mode == FT_PIXEL_MODE_BGRA ) {
1101- /* paste color glyph */
1102- for (k = x0 ; k < x1 ; k ++ ) {
1103- unsigned int src_alpha = source [k * 4 + 3 ];
1104-
1105- /* paste only if source has data */
1106- if (src_alpha > 0 ) {
1107- /* unpremultiply BGRa */
1108- int src_red =
1109- CLIP8 ((255 * (int )source [k * 4 + 2 ]) / src_alpha );
1110- int src_green =
1111- CLIP8 ((255 * (int )source [k * 4 + 1 ]) / src_alpha );
1112- int src_blue =
1113- CLIP8 ((255 * (int )source [k * 4 + 0 ]) / src_alpha );
1114-
1115- /* blend required if target has data */
1116- if (target [k * 4 + 3 ] > 0 ) {
1117- /* blend RGBA colors */
1118- target [k * 4 + 0 ] =
1119- BLEND (src_alpha , target [k * 4 + 0 ], src_red , tmp );
1120- target [k * 4 + 1 ] =
1121- BLEND (src_alpha , target [k * 4 + 1 ], src_green , tmp );
1122- target [k * 4 + 2 ] =
1123- BLEND (src_alpha , target [k * 4 + 2 ], src_blue , tmp );
1124- target [k * 4 + 3 ] = CLIP8 (
1125- src_alpha +
1126- MULDIV255 (target [k * 4 + 3 ], (255 - src_alpha ), tmp )
1127- );
1128- } else {
1129- /* paste unpremultiplied RGBA values */
1130- target [k * 4 + 0 ] = src_red ;
1131- target [k * 4 + 1 ] = src_green ;
1132- target [k * 4 + 2 ] = src_blue ;
1133- target [k * 4 + 3 ] = src_alpha ;
1134- }
1135- }
1136- }
1137- } else if (bitmap .pixel_mode == FT_PIXEL_MODE_GRAY ) {
1080+ source = (unsigned char * )bitmap .buffer ;
1081+ for (bitmap_y = 0 ; bitmap_y < bitmap .rows ; bitmap_y ++ , yy ++ ) {
1082+ /* clip glyph bitmap height to target image bounds */
1083+ if (yy >= 0 && yy < im -> ysize ) {
1084+ /* blend this glyph into the buffer */
1085+ int k ;
1086+ unsigned char * target ;
1087+ unsigned int tmp ;
11381088 if (color ) {
1139- unsigned char * ink = (unsigned char * )& foreground_ink ;
1089+ /* target[RGB] returns the color, target[A] returns the mask */
1090+ /* target bands get split again in ImageDraw.text */
1091+ target = (unsigned char * )im -> image [yy ] + xx * 4 ;
1092+ } else {
1093+ target = im -> image8 [yy ] + xx ;
1094+ }
1095+ if (color && bitmap .pixel_mode == FT_PIXEL_MODE_BGRA ) {
1096+ /* paste color glyph */
11401097 for (k = x0 ; k < x1 ; k ++ ) {
1141- unsigned int src_alpha = source [k ] * convert_scale ;
1098+ unsigned int src_alpha = source [k * 4 + 3 ];
1099+
1100+ /* paste only if source has data */
11421101 if (src_alpha > 0 ) {
1102+ /* unpremultiply BGRa */
1103+ int src_red =
1104+ CLIP8 ((255 * (int )source [k * 4 + 2 ]) / src_alpha );
1105+ int src_green =
1106+ CLIP8 ((255 * (int )source [k * 4 + 1 ]) / src_alpha );
1107+ int src_blue =
1108+ CLIP8 ((255 * (int )source [k * 4 + 0 ]) / src_alpha );
1109+
1110+ /* blend required if target has data */
11431111 if (target [k * 4 + 3 ] > 0 ) {
1112+ /* blend RGBA colors */
11441113 target [k * 4 + 0 ] = BLEND (
1145- src_alpha , target [k * 4 + 0 ], ink [ 0 ] , tmp
1114+ src_alpha , target [k * 4 + 0 ], src_red , tmp
11461115 );
11471116 target [k * 4 + 1 ] = BLEND (
1148- src_alpha , target [k * 4 + 1 ], ink [ 1 ] , tmp
1117+ src_alpha , target [k * 4 + 1 ], src_green , tmp
11491118 );
11501119 target [k * 4 + 2 ] = BLEND (
1151- src_alpha , target [k * 4 + 2 ], ink [ 2 ] , tmp
1120+ src_alpha , target [k * 4 + 2 ], src_blue , tmp
11521121 );
11531122 target [k * 4 + 3 ] = CLIP8 (
11541123 src_alpha +
@@ -1157,35 +1126,68 @@ font_render(FontObject *self, PyObject *args) {
11571126 )
11581127 );
11591128 } else {
1160- target [k * 4 + 0 ] = ink [0 ];
1161- target [k * 4 + 1 ] = ink [1 ];
1162- target [k * 4 + 2 ] = ink [2 ];
1129+ /* paste unpremultiplied RGBA values */
1130+ target [k * 4 + 0 ] = src_red ;
1131+ target [k * 4 + 1 ] = src_green ;
1132+ target [k * 4 + 2 ] = src_blue ;
11631133 target [k * 4 + 3 ] = src_alpha ;
11641134 }
11651135 }
11661136 }
1167- } else {
1168- for (k = x0 ; k < x1 ; k ++ ) {
1169- unsigned int src_alpha = source [k ] * convert_scale ;
1170- if (src_alpha > 0 ) {
1171- target [k ] =
1172- target [k ] > 0
1173- ? CLIP8 (
1174- src_alpha +
1175- MULDIV255 (
1176- target [k ], (255 - src_alpha ), tmp
1137+ } else if (bitmap .pixel_mode == FT_PIXEL_MODE_GRAY ) {
1138+ if (color ) {
1139+ unsigned char * ink = (unsigned char * )& foreground_ink ;
1140+ for (k = x0 ; k < x1 ; k ++ ) {
1141+ unsigned int src_alpha = source [k ] * convert_scale ;
1142+ if (src_alpha > 0 ) {
1143+ if (target [k * 4 + 3 ] > 0 ) {
1144+ target [k * 4 + 0 ] = BLEND (
1145+ src_alpha , target [k * 4 + 0 ], ink [0 ], tmp
1146+ );
1147+ target [k * 4 + 1 ] = BLEND (
1148+ src_alpha , target [k * 4 + 1 ], ink [1 ], tmp
1149+ );
1150+ target [k * 4 + 2 ] = BLEND (
1151+ src_alpha , target [k * 4 + 2 ], ink [2 ], tmp
1152+ );
1153+ target [k * 4 + 3 ] = CLIP8 (
1154+ src_alpha + MULDIV255 (
1155+ target [k * 4 + 3 ],
1156+ (255 - src_alpha ),
1157+ tmp
1158+ )
1159+ );
1160+ } else {
1161+ target [k * 4 + 0 ] = ink [0 ];
1162+ target [k * 4 + 1 ] = ink [1 ];
1163+ target [k * 4 + 2 ] = ink [2 ];
1164+ target [k * 4 + 3 ] = src_alpha ;
1165+ }
1166+ }
1167+ }
1168+ } else {
1169+ for (k = x0 ; k < x1 ; k ++ ) {
1170+ unsigned int src_alpha = source [k ] * convert_scale ;
1171+ if (src_alpha > 0 ) {
1172+ target [k ] =
1173+ target [k ] > 0
1174+ ? CLIP8 (
1175+ src_alpha +
1176+ MULDIV255 (
1177+ target [k ], (255 - src_alpha ), tmp
1178+ )
11771179 )
1178- )
1179- : src_alpha ;
1180+ : src_alpha ;
1181+ }
11801182 }
11811183 }
1184+ } else {
1185+ PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1186+ goto glyph_error ;
11821187 }
1183- } else {
1184- PyErr_SetString (PyExc_OSError , "unsupported bitmap pixel mode" );
1185- goto glyph_error ;
11861188 }
1189+ source += bitmap .pitch ;
11871190 }
1188- source += bitmap .pitch ;
11891191 }
11901192 x += glyph_info [i ].x_advance ;
11911193 y += glyph_info [i ].y_advance ;
0 commit comments