trunk/src/emu/rendlay.c
| r29197 | r29198 | |
| 666 | 666 | m_stateoffset = xml_get_attribute_int_with_subst(machine, compnode, "stateoffset", 0); |
| 667 | 667 | m_numsymbolsvisible = xml_get_attribute_int_with_subst(machine, compnode, "numsymbolsvisible", 3); |
| 668 | 668 | m_reelreversed = xml_get_attribute_int_with_subst(machine, compnode, "reelreversed", 0); |
| 669 | m_beltreel = xml_get_attribute_int_with_subst(machine, compnode, "beltreel", 0); |
| 670 | |
| 669 | 671 | } |
| 670 | 672 | |
| 671 | 673 | // led7seg nodes |
| r29197 | r29198 | |
| 981 | 983 | /* state is a normalized value between 0 and 65536 so that we don't need to worry about how many motor steps here or in the .lay, only the number of symbols */ |
| 982 | 984 | void layout_element::component::draw_reel(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) |
| 983 | 985 | { |
| 986 | if (m_beltreel) |
| 987 | { |
| 988 | draw_beltreel(machine,dest,bounds,state); |
| 989 | } |
| 990 | else |
| 991 | { |
| 992 | const int max_state_used = 0x10000; |
| 993 | |
| 994 | // shift the reels a bit based on this param, allows fine tuning |
| 995 | int use_state = (state + m_stateoffset) % max_state_used; |
| 996 | |
| 997 | // compute premultiplied colors |
| 998 | UINT32 r = m_color.r * 255.0; |
| 999 | UINT32 g = m_color.g * 255.0; |
| 1000 | UINT32 b = m_color.b * 255.0; |
| 1001 | UINT32 a = m_color.a * 255.0; |
| 1002 | |
| 1003 | // get the width of the string |
| 1004 | render_font *font = machine.render().font_alloc("default"); |
| 1005 | float aspect = 1.0f; |
| 1006 | INT32 width; |
| 1007 | |
| 1008 | |
| 1009 | int curry = 0; |
| 1010 | int num_shown = m_numsymbolsvisible; |
| 1011 | |
| 1012 | int ourheight = bounds.height(); |
| 1013 | |
| 1014 | for (int fruit = 0;fruit<m_numstops;fruit++) |
| 1015 | { |
| 1016 | int basey; |
| 1017 | |
| 1018 | if (m_reelreversed==1) |
| 1019 | { |
| 1020 | basey = bounds.min_y + ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; |
| 1021 | } |
| 1022 | else |
| 1023 | { |
| 1024 | basey = bounds.min_y - ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; |
| 1025 | } |
| 1026 | |
| 1027 | // wrap around... |
| 1028 | if (basey < bounds.min_y) |
| 1029 | basey += ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); |
| 1030 | if (basey > bounds.max_y) |
| 1031 | basey -= ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); |
| 1032 | |
| 1033 | int endpos = basey+ourheight/num_shown; |
| 1034 | |
| 1035 | // only render the symbol / text if it's atually in view because the code is SLOW |
| 1036 | if ((endpos >= bounds.min_y) && (basey <= bounds.max_y)) |
| 1037 | { |
| 1038 | while (1) |
| 1039 | { |
| 1040 | width = font->string_width(ourheight/num_shown, aspect, m_stopnames[fruit]); |
| 1041 | if (width < bounds.width()) |
| 1042 | break; |
| 1043 | aspect *= 0.9f; |
| 1044 | } |
| 1045 | |
| 1046 | INT32 curx; |
| 1047 | curx = bounds.min_x + (bounds.width() - width) / 2; |
| 1048 | |
| 1049 | if (m_file[fruit]) |
| 1050 | if (!m_bitmap[fruit].valid()) |
| 1051 | load_reel_bitmap(fruit); |
| 1052 | |
| 1053 | if (m_file[fruit]) // render gfx |
| 1054 | { |
| 1055 | bitmap_argb32 tempbitmap2(dest.width(), ourheight/num_shown); |
| 1056 | |
| 1057 | if (m_bitmap[fruit].valid()) |
| 1058 | { |
| 1059 | render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], m_color); |
| 1060 | |
| 1061 | for (int y = 0; y < ourheight/num_shown; y++) |
| 1062 | { |
| 1063 | int effy = basey + y; |
| 1064 | |
| 1065 | if (effy >= bounds.min_y && effy <= bounds.max_y) |
| 1066 | { |
| 1067 | UINT32 *src = &tempbitmap2.pix32(y); |
| 1068 | UINT32 *d = &dest.pix32(effy); |
| 1069 | for (int x = 0; x < dest.width(); x++) |
| 1070 | { |
| 1071 | int effx = x; |
| 1072 | if (effx >= bounds.min_x && effx <= bounds.max_x) |
| 1073 | { |
| 1074 | UINT32 spix = rgb_t(src[x]).a(); |
| 1075 | if (spix != 0) |
| 1076 | { |
| 1077 | d[effx] = src[x]; |
| 1078 | } |
| 1079 | } |
| 1080 | } |
| 1081 | } |
| 1082 | |
| 1083 | } |
| 1084 | } |
| 1085 | } |
| 1086 | else // render text (fallback) |
| 1087 | { |
| 1088 | // allocate a temporary bitmap |
| 1089 | bitmap_argb32 tempbitmap(dest.width(), dest.height()); |
| 1090 | |
| 1091 | // loop over characters |
| 1092 | for (const char *s = m_stopnames[fruit]; *s != 0; s++) |
| 1093 | { |
| 1094 | // get the font bitmap |
| 1095 | rectangle chbounds; |
| 1096 | font->get_scaled_bitmap_and_bounds(tempbitmap, ourheight/num_shown, aspect, *s, chbounds); |
| 1097 | |
| 1098 | // copy the data into the target |
| 1099 | for (int y = 0; y < chbounds.height(); y++) |
| 1100 | { |
| 1101 | int effy = basey + y; |
| 1102 | |
| 1103 | if (effy >= bounds.min_y && effy <= bounds.max_y) |
| 1104 | { |
| 1105 | UINT32 *src = &tempbitmap.pix32(y); |
| 1106 | UINT32 *d = &dest.pix32(effy); |
| 1107 | for (int x = 0; x < chbounds.width(); x++) |
| 1108 | { |
| 1109 | int effx = curx + x + chbounds.min_x; |
| 1110 | if (effx >= bounds.min_x && effx <= bounds.max_x) |
| 1111 | { |
| 1112 | UINT32 spix = rgb_t(src[x]).a(); |
| 1113 | if (spix != 0) |
| 1114 | { |
| 1115 | rgb_t dpix = d[effx]; |
| 1116 | UINT32 ta = (a * (spix + 1)) >> 8; |
| 1117 | UINT32 tr = (r * ta + dpix.r() * (0x100 - ta)) >> 8; |
| 1118 | UINT32 tg = (g * ta + dpix.g() * (0x100 - ta)) >> 8; |
| 1119 | UINT32 tb = (b * ta + dpix.b() * (0x100 - ta)) >> 8; |
| 1120 | d[effx] = rgb_t(tr, tg, tb); |
| 1121 | } |
| 1122 | } |
| 1123 | } |
| 1124 | } |
| 1125 | } |
| 1126 | |
| 1127 | // advance in the X direction |
| 1128 | curx += font->char_width(ourheight/num_shown, aspect, *s); |
| 1129 | |
| 1130 | } |
| 1131 | |
| 1132 | } |
| 1133 | } |
| 1134 | |
| 1135 | curry += ourheight/num_shown; |
| 1136 | } |
| 1137 | // free the temporary bitmap and font |
| 1138 | machine.render().font_free(font); |
| 1139 | } |
| 1140 | } |
| 1141 | |
| 1142 | |
| 1143 | void layout_element::component::draw_beltreel(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) |
| 1144 | { |
| 984 | 1145 | const int max_state_used = 0x10000; |
| 985 | 1146 | |
| 986 | 1147 | // shift the reels a bit based on this param, allows fine tuning |
| r29197 | r29198 | |
| 996 | 1157 | render_font *font = machine.render().font_alloc("default"); |
| 997 | 1158 | float aspect = 1.0f; |
| 998 | 1159 | INT32 width; |
| 999 | | int curry = 0; |
| 1160 | int currx = 0; |
| 1000 | 1161 | int num_shown = m_numsymbolsvisible; |
| 1001 | 1162 | |
| 1002 | | int ourheight = bounds.height(); |
| 1163 | int ourwidth = bounds.width(); |
| 1003 | 1164 | |
| 1004 | 1165 | for (int fruit = 0;fruit<m_numstops;fruit++) |
| 1005 | 1166 | { |
| 1006 | | int basey; |
| 1007 | | |
| 1167 | int basex; |
| 1008 | 1168 | if (m_reelreversed==1) |
| 1009 | 1169 | { |
| 1010 | | basey = bounds.min_y + ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; |
| 1170 | basex = bounds.min_x + ((use_state)*(ourwidth/num_shown)/(max_state_used/m_numstops)) + currx; |
| 1011 | 1171 | } |
| 1012 | 1172 | else |
| 1013 | 1173 | { |
| 1014 | | basey = bounds.min_y - ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; |
| 1174 | basex = bounds.min_x - ((use_state)*(ourwidth/num_shown)/(max_state_used/m_numstops)) + currx; |
| 1015 | 1175 | } |
| 1016 | 1176 | |
| 1017 | 1177 | // wrap around... |
| 1018 | | if (basey < bounds.min_y) |
| 1019 | | basey += ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); |
| 1020 | | if (basey > bounds.max_y) |
| 1021 | | basey -= ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); |
| 1178 | if (basex < bounds.min_x) |
| 1179 | basex += ((max_state_used)*(ourwidth/num_shown)/(max_state_used/m_numstops)); |
| 1180 | if (basex > bounds.max_x) |
| 1181 | basex -= ((max_state_used)*(ourwidth/num_shown)/(max_state_used/m_numstops)); |
| 1022 | 1182 | |
| 1023 | | int endpos = basey+ourheight/num_shown; |
| 1183 | int endpos = basex+(ourwidth/num_shown); |
| 1024 | 1184 | |
| 1025 | 1185 | // only render the symbol / text if it's atually in view because the code is SLOW |
| 1026 | | if ((endpos >= bounds.min_y) && (basey <= bounds.max_y)) |
| 1186 | if ((endpos >= bounds.min_x) && (basex <= bounds.max_x)) |
| 1027 | 1187 | { |
| 1028 | 1188 | while (1) |
| 1029 | 1189 | { |
| 1030 | | width = font->string_width(ourheight/num_shown, aspect, m_stopnames[fruit]); |
| 1190 | width = font->string_width(dest.height(), aspect, m_stopnames[fruit]); |
| 1031 | 1191 | if (width < bounds.width()) |
| 1032 | 1192 | break; |
| 1033 | 1193 | aspect *= 0.9f; |
| 1034 | 1194 | } |
| 1035 | 1195 | |
| 1036 | 1196 | INT32 curx; |
| 1037 | | curx = bounds.min_x + (bounds.width() - width) / 2; |
| 1197 | curx = bounds.min_x; |
| 1038 | 1198 | |
| 1039 | 1199 | if (m_file[fruit]) |
| 1040 | 1200 | if (!m_bitmap[fruit].valid()) |
| r29197 | r29198 | |
| 1042 | 1202 | |
| 1043 | 1203 | if (m_file[fruit]) // render gfx |
| 1044 | 1204 | { |
| 1045 | | bitmap_argb32 tempbitmap2(dest.width(), ourheight/num_shown); |
| 1205 | bitmap_argb32 tempbitmap2(ourwidth/num_shown, dest.height()); |
| 1046 | 1206 | |
| 1047 | 1207 | if (m_bitmap[fruit].valid()) |
| 1048 | 1208 | { |
| 1049 | 1209 | render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], m_color); |
| 1050 | 1210 | |
| 1051 | | for (int y = 0; y < ourheight/num_shown; y++) |
| 1211 | for (int y = 0; y < dest.height(); y++) |
| 1052 | 1212 | { |
| 1053 | | int effy = basey + y; |
| 1213 | int effy = y; |
| 1054 | 1214 | |
| 1055 | 1215 | if (effy >= bounds.min_y && effy <= bounds.max_y) |
| 1056 | 1216 | { |
| 1057 | 1217 | UINT32 *src = &tempbitmap2.pix32(y); |
| 1058 | 1218 | UINT32 *d = &dest.pix32(effy); |
| 1059 | | for (int x = 0; x < dest.width(); x++) |
| 1219 | for (int x = 0; x < ourwidth/num_shown; x++) |
| 1060 | 1220 | { |
| 1061 | | int effx = x; |
| 1221 | int effx = basex + x; |
| 1062 | 1222 | if (effx >= bounds.min_x && effx <= bounds.max_x) |
| 1063 | 1223 | { |
| 1064 | 1224 | UINT32 spix = rgb_t(src[x]).a(); |
| r29197 | r29198 | |
| 1083 | 1243 | { |
| 1084 | 1244 | // get the font bitmap |
| 1085 | 1245 | rectangle chbounds; |
| 1086 | | font->get_scaled_bitmap_and_bounds(tempbitmap, ourheight/num_shown, aspect, *s, chbounds); |
| 1246 | font->get_scaled_bitmap_and_bounds(tempbitmap, dest.height(), aspect, *s, chbounds); |
| 1087 | 1247 | |
| 1088 | 1248 | // copy the data into the target |
| 1089 | 1249 | for (int y = 0; y < chbounds.height(); y++) |
| 1090 | 1250 | { |
| 1091 | | int effy = basey + y; |
| 1251 | int effy = y; |
| 1092 | 1252 | |
| 1093 | 1253 | if (effy >= bounds.min_y && effy <= bounds.max_y) |
| 1094 | 1254 | { |
| r29197 | r29198 | |
| 1096 | 1256 | UINT32 *d = &dest.pix32(effy); |
| 1097 | 1257 | for (int x = 0; x < chbounds.width(); x++) |
| 1098 | 1258 | { |
| 1099 | | int effx = curx + x + chbounds.min_x; |
| 1259 | int effx = basex + curx + x; |
| 1100 | 1260 | if (effx >= bounds.min_x && effx <= bounds.max_x) |
| 1101 | 1261 | { |
| 1102 | | UINT32 spix = rgb_t(src[x]).a(); |
| 1262 | UINT32 spix = rgb_t(src[x]).a(); |
| 1103 | 1263 | if (spix != 0) |
| 1104 | 1264 | { |
| 1105 | 1265 | rgb_t dpix = d[effx]; |
| r29197 | r29198 | |
| 1115 | 1275 | } |
| 1116 | 1276 | |
| 1117 | 1277 | // advance in the X direction |
| 1118 | | curx += font->char_width(ourheight/num_shown, aspect, *s); |
| 1278 | curx += font->char_width(dest.height(), aspect, *s); |
| 1119 | 1279 | |
| 1120 | 1280 | } |
| 1121 | 1281 | |
| 1122 | 1282 | } |
| 1123 | 1283 | } |
| 1124 | 1284 | |
| 1125 | | curry += ourheight/num_shown; |
| 1285 | currx += ourwidth/num_shown; |
| 1126 | 1286 | } |
| 1127 | 1287 | |
| 1128 | 1288 | // free the temporary bitmap and font |
| r29197 | r29198 | |
| 1130 | 1290 | } |
| 1131 | 1291 | |
| 1132 | 1292 | |
| 1133 | | |
| 1134 | | |
| 1135 | 1293 | //------------------------------------------------- |
| 1136 | 1294 | // load_bitmap - load a PNG file with artwork for |
| 1137 | 1295 | // a component |