void advance_ui_buffer_update(struct advance_ui_context* context, void* ptr, unsigned dx, unsigned dy, unsigned dw, adv_color_def color_def, adv_color_rgb* palette_map, unsigned palette_max) { adv_bitmap* dst; struct ui_color_set* color = &context->state.color_map; ui_setup_color(context, color, color_def, palette_map, palette_max); dst = adv_bitmap_import_rgb(dx, dy, color_def_bytes_per_pixel_get(color_def), 0, 0, ptr, dw); context->state.ui_extra_flag = 0; if (context->state.ui_help_flag) { ui_help_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_menu_flag) { ui_menu_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_message_flag) { ui_message_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_osd_flag) { ui_osd_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_scroll_flag) { ui_scroll_update(context, dst, color); context->state.ui_extra_flag = 1; } adv_bitmap_free(dst); }
void advance_ui_inner_done(struct advance_ui_context* context) { adv_font_free(context->state.ui_font); context->state.ui_font = 0; adv_font_free(context->state.ui_font_oriented); context->state.ui_font_oriented = 0; if (context->state.help_image) { adv_bitmap_free(context->state.help_image); context->state.help_image = 0; } }
static void ui_messagebox_center(struct advance_ui_context* context, adv_bitmap* dst, int x, int y, const char* begin, const char* end, struct ui_color cf, struct ui_color cb, adv_pixel* map, adv_color_def def) { int border_x, border_y; int size_x, size_y; int pos_x, pos_y; adv_bitmap* flat; border_x = adv_font_sizex(context->state.ui_font); border_y = adv_font_sizey(context->state.ui_font) / 2; end = adv_font_sizex_limit(context->state.ui_font, begin, end, dst->size_x - border_x * 2); size_x = border_x * 2 + adv_font_sizex_string(context->state.ui_font, begin, end); size_y = border_y * 2 + adv_font_sizey(context->state.ui_font); pos_x = x - size_x / 2; pos_y = y - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, cf.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, cb.b); if (ui_alpha(def)) adv_font_put_string_map(context->state.ui_font, flat, border_x, border_y, begin, end, map); else adv_font_put_string(context->state.ui_font, flat, border_x, border_y, begin, end, cf.p, cb.p); if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }
void advance_ui_direct_update(struct advance_ui_context* context, void* ptr, unsigned dx, unsigned dy, unsigned dw, adv_color_def color_def, adv_color_rgb* palette_map, unsigned palette_max) { adv_bitmap* dst; struct ui_color_set color; ui_setup_color(context, &color, color_def, palette_map, palette_max); dst = adv_bitmap_import_rgb(dx, dy, color_def_bytes_per_pixel_get(color_def), 0, 0, ptr, dw); if (context->state.ui_direct_slow_flag) { ui_direct_slow_update(context, dst, &color); } if (context->state.ui_direct_fast_flag) { ui_direct_fast_update(context, dst, &color); } if (context->state.ui_direct_text_flag) { ui_direct_text_update(context, dst, &color); } adv_bitmap_free(dst); }
static void ui_help_update(struct advance_ui_context* context, adv_bitmap* dst, struct ui_color_set* color) { int size_x; int size_y; int pos_x; int pos_y; unsigned cx; unsigned cy; unsigned i; unsigned pb; char msg_buffer[256]; adv_bitmap* flat; adv_color_def def = color->def; struct mame_digital_map_entry digital_map[UI_MAP_MAX]; unsigned digital_mac; mame_ui_input_map(&digital_mac, digital_map, UI_MAP_MAX); size_x = context->state.help_image->size_x; size_y = context->state.help_image->size_y; pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 8; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); pb = 0; /* black on RGB format */ for (cy = 0; cy < context->state.help_image->size_y; ++cy) { for (cx = 0; cx < context->state.help_image->size_x; ++cx) { adv_pixel c; if ((adv_bitmap_pixel_get(context->state.help_image, cx, cy)) != pb) { c = color->ui_f.f; } else { c = color->ui_b.b; } adv_bitmap_pixel_put(flat, cx, cy, c); } } msg_buffer[0] = 0; for (i = 0; i < digital_mac; ++i) { unsigned j; adv_bool pred_not = 0; if (digital_map[i].port_state) { struct mame_port* p; p = mame_port_find(digital_map[i].port); if (p) { unsigned k; /* add the port name only one time */ /* if the port list is broken, a port name may appers more than one time */ for (k = 0; k < i; ++k) if (digital_map[k].port == digital_map[i].port) break; if (k == i) { if (msg_buffer[0]) sncat(msg_buffer, sizeof(msg_buffer), ", "); sncat(msg_buffer, sizeof(msg_buffer), p->desc); } } } for (j = 0; j < MAME_INPUT_MAP_MAX && digital_map[i].seq[j] != DIGITAL_SPECIAL_NONE; ++j) { if (!pred_not) { unsigned k; unsigned ckf; unsigned ckb; switch (mame_port_player(digital_map[i].port)) { case 1: ckb = color->help_p1.b; break; case 2: ckb = color->help_p2.b; break; case 3: ckb = color->help_p3.b; break; case 4: ckb = color->help_p4.b; break; default: ckb = color->help_u.b; break; } ckf = color->ui_f.f; if (digital_map[i].port_state) { ckf = color->ui_f.f; ckb = color->ui_f.b; } for (k = 0; k < context->config.help_mac; ++k) { if (context->config.help_map[k].code == digital_map[i].seq[j]) { struct help_entry* h = context->config.help_map + k; ui_help_update_key(flat, context->state.help_image, 0, 0, h->x, h->y, h->dx, h->dy, ckf, ckb, pb); } } } pred_not = digital_map[i].seq[j] == DIGITAL_SPECIAL_NOT; } } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); if (msg_buffer[0]) ui_messagebox_center(context, dst, dst->size_x / 2, pos_y + size_y + adv_font_sizey(context->state.ui_font) * 2, msg_buffer, msg_buffer + strlen(msg_buffer), color->ui_f, color->ui_b, color->ui_alpha, color->def); }
static void ui_scroll(struct advance_ui_context* context, adv_bitmap* dst, char* begin, char* end, unsigned pos, struct ui_color text_f, struct ui_color text_b, adv_pixel* text_map, struct ui_color title_f, struct ui_color title_b, adv_pixel* title_map, adv_color_def def) { unsigned size_r; unsigned size_v; int step_x, step_y; int border_x, border_y; int size_x, size_y; int pos_x, pos_y; int limit_x; char* i; char* start; unsigned n; adv_bitmap* flat; step_x = adv_font_sizex(context->state.ui_font); step_y = adv_font_sizey(context->state.ui_font); border_x = step_x; border_y = step_y / 2; /* remove unprintable chars */ i = begin; while (i != end) { if (!((*i >= ' ' && *i <= '~') || *i == '\n')) *i = ' '; ++i; } /* count size_r and compute width and wrap long line */ limit_x = dst->size_x - 6 * border_x; size_r = 0; size_x = 0; i = begin; start = begin; while (i != end) { unsigned width; char* j = i; width = 0; while (j != end && *j != '\n') { unsigned char_width; char_width = adv_font_sizex_char(context->state.ui_font, *j); if (width + char_width > limit_x) { char* b = j; /* search first space backward */ while (b != i && !isspace(*b)) --b; if (b != i) { /* adjust the position */ if (pos > size_r) ++pos; /* insert a break */ *b = '\n'; j = b; break; } } else { width += char_width; } ++j; } if (size_r == pos) start = i; ++size_r; width = adv_font_sizex_string(context->state.ui_font, i, j); if (width > size_x) size_x = width; if (j != end) i = j + 1; else i = j; } /* size */ size_x += 2 * border_x; if (size_x > dst->size_x) size_x = dst->size_x; size_v = (dst->size_y - 4 * border_y) / step_y; if (size_v > size_r) size_v = size_r; size_y = size_v * step_y + 2 * border_y; /* position */ pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 2 - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); /* put */ adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, text_f.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, text_b.b); n = 0; i = start; while (i != end && n < size_v) { struct ui_color f; struct ui_color b; adv_pixel* m; char* k; char* j = i; const char* je; while (j != end && *j != '\n') ++j; je = adv_font_sizex_limit(context->state.ui_font, i, j, size_x - 2 * border_x); for (k = i; k != j; ++k) { if (islower(*k)) break; } if (ui_recognize_title(i, j)) { f = title_f; b = title_b; m = title_map; } else { f = text_f; b = text_b; m = text_map; } ui_text_left(context, flat, border_x, border_y + n * step_y, i, je, f, b, m, def); if (j != end) i = j + 1; else i = j; ++n; } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }
static void ui_menu(struct advance_ui_context* context, adv_bitmap* dst, struct ui_menu_entry* menu_map, unsigned menu_mac, int menu_sel, struct ui_color entry_f, struct ui_color entry_b, adv_pixel* entry_map, struct ui_color select_f, struct ui_color select_b, adv_pixel* select_map, struct ui_color title_f, struct ui_color title_b, adv_pixel* title_map, adv_color_def def) { int step_x, step_y; int border_x, border_y; int size_x, size_y; int pos_x, pos_y; int pos_r; int pos_s; int size_r; unsigned i; unsigned y; unsigned dft_dx; unsigned dft_dy; int up; int down; adv_bitmap* flat; step_x = adv_font_sizex(context->state.ui_font); step_y = adv_font_sizey(context->state.ui_font); dft_dx = dst->size_x * 3 / 4; dft_dy = dst->size_y * 2 / 5; border_x = step_x; border_y = step_y / 2; /* compute the size of the menu */ size_x = border_x * 2; size_y = border_y * 2; /* search the selected position */ pos_r = 0; pos_s = 0; for (i = 0; i < menu_mac; ++i) { switch (menu_map[i].type) { case ui_menu_text: case ui_menu_option: if (menu_sel == pos_r) { pos_s = i; } ++pos_r; break; default: break; } } up = 0; down = 0; size_r = 0; pos_r = pos_s; while (1) { unsigned width; unsigned height; if (size_r == 0) { i = pos_r; } else if (up <= down && pos_r > 0) { i = pos_r - 1; } else if (up > down && pos_r + size_r < menu_mac) { i = pos_r + size_r; } else if (pos_r > 0) { i = pos_r - 1; } else if (pos_r + size_r < menu_mac) { i = pos_r + size_r; } else { break; } switch (menu_map[i].type) { case ui_menu_title: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); height = step_y; break; case ui_menu_text: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); height = step_y; break; case ui_menu_option: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); width += border_x * 3 + adv_font_sizex_string(context->state.ui_font, menu_map[i].option_buffer, menu_map[i].option_buffer + strlen(menu_map[i].option_buffer)); height = step_y; break; case ui_menu_dft: width = dft_dx; height = dft_dy; break; default: width = 0; height = 0; break; } if (size_y + height > dst->size_y) break; size_y += height; if (size_x < width) size_x = width; if (i == pos_r) { ++size_r; } else if (i < pos_r) { up += height; --pos_r; ++size_r; } else if (i > pos_r) { down += height; ++size_r; } } if (size_x > dst->size_x) size_x = dst->size_x; /* position */ pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 2 - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); /* put */ adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, entry_f.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, entry_b.b); y = border_y; for (i = 0; i < size_r; ++i) { struct ui_menu_entry* e = &menu_map[i + pos_r]; struct ui_color cef; struct ui_color ceb; struct ui_color ctf; struct ui_color ctb; adv_pixel* cem; adv_pixel* ctm; unsigned height = e->type == ui_menu_dft ? dft_dy : step_y; unsigned width = size_x - 2 * border_x; if (i + pos_r == pos_s) { cef = select_f; ceb = select_b; cem = select_map; ctf = select_f; ctb = select_b; ctm = select_map; } else { cef = entry_f; ceb = entry_b; cem = entry_map; ctf = title_f; ctb = title_b; ctm = title_map; } adv_bitmap_clear(flat, border_x / 2, y, size_x - (border_x / 2) * 2, height, ceb.b); if (e->type == ui_menu_option) { const char* begin = e->text_buffer; const char* end = e->text_buffer + strlen(e->text_buffer); end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_left(context, flat, border_x, y, begin, end, cef, ceb, cem, def); width -= adv_font_sizex_string(context->state.ui_font, begin, end); begin = e->option_buffer; end = e->option_buffer + strlen(e->option_buffer); end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_right(context, flat, size_x - border_x, y, begin, end, ctf, ctb, ctm, def); } else if (e->type == ui_menu_title || e->type == ui_menu_text) { const char* begin = e->text_buffer; const char* end = e->text_buffer + strlen(e->text_buffer); adv_bool title = e->type == ui_menu_title; end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_center(context, flat, size_x / 2, y, begin, end, title ? ctf : cef, title ? ctb : ceb, title ? ctm : cem, def); } else if (e->type == ui_menu_dft) { ui_dft(context, flat, border_x, y + border_y, size_x - border_x * 2, height - border_y * 2, e->m, e->n, e->cut1, e->cut2, cef, ceb, ctf, def); } y += height; } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }
/** * Load a .pcx file in a bitmap. * Only the 8 and 24 bits format are supported. * \param f File to load. * \param rgb Where to put the palette information. it must point to a vector of 256 elements. * \param rgb_max Where to put the number of palette entries. * \return The loaded bitmap or 0 on error. */ adv_bitmap* adv_bitmap_load_pcx(adv_color_rgb* rgb, unsigned* rgb_max, adv_fz* f) { struct pcx_header_t h; adv_bitmap* bitmap; unsigned width, height, depth; if (pcx_header_read(f, &h)!=0) { goto out; } /* limitations */ if (h.bits_per_pixel != 8) { goto out; } if (h.planes != 1 && h.planes != 3) { goto out; } width = h.x_max - h.x_min + 1; height = h.y_max - h.y_min + 1; depth = h.planes; bitmap = adv_bitmap_alloc(width, height, depth); if (!bitmap) { goto out; } if (depth == 1) { unsigned i; unsigned y; for(y=0; y<height; ++y) { struct pcx_decode_state state; uint8* dst_off = adv_bitmap_line(bitmap, y); state.count = 0; pcx_decode(dst_off, width, f, &state, 1); pcx_ignore(h.bytes_per_line - width, f, &state); if (state.count!=0) goto out_bitmap; } if (fzgetc(f)!=12) goto out_bitmap; for (i=0; i<256; ++i) { rgb[i].red = fzgetc(f); rgb[i].green = fzgetc(f); rgb[i].blue = fzgetc(f); } *rgb_max = 256; } else { unsigned y; for(y=0; y<height; ++y) { struct pcx_decode_state state; uint8* dst_off = adv_bitmap_line(bitmap, y); state.count = 0; pcx_decode(dst_off, width, f, &state, 3); pcx_ignore(h.bytes_per_line - width, f, &state); pcx_decode(dst_off + 1, width, f, &state, 3); pcx_ignore(h.bytes_per_line - width, f, &state); pcx_decode(dst_off + 2, width, f, &state, 3); pcx_ignore(h.bytes_per_line - width, f, &state); if (state.count!=0) goto out_bitmap; } } return bitmap; out_bitmap: adv_bitmap_free(bitmap); out: return 0; }
/** * Load a .ico file in a bitmap. * Only the 16 and 256 color formats are supported. * \param f File to load. * \param rgb Where to put the palette information. it must point to a vector of 256 elements. * \param rgb_max Where to put the number of palette entries. * \param bitmap_mask Where to put the mask bitmap. * \return The loaded bitmap or 0 on error. */ adv_bitmap* adv_bitmap_load_icon(adv_color_rgb* rgb, unsigned* rgb_max, adv_bitmap** bitmap_mask, adv_fz* f) { adv_bitmap* bitmap; struct icon_header_t header; struct icon_entry_t* entry; int i; if (icon_header_read(f, &header) != 0) goto out; if (header.reserved != 0) goto out; if (header.type != 1) goto out; if (header.count < 1) goto out; entry = malloc(header.count * sizeof(struct icon_entry_t)); if (!entry) goto out; for(i=0;i<header.count;++i) { if (icon_entry_read(f, entry + i)!=0) goto out_entry; } for(i=0;i<header.count;++i) { struct icon_bitmap_header_t bitmap_header; unsigned j, y; unsigned colors; if (entry[i].color == 0) { colors = 256; if (entry[i].bit != 8 && entry[i].bit != 0) /* 0 is out of standard but acceptable */ continue; /* unsupported */ } else if (entry[i].color == 16) { colors = 16; if (entry[i].bit != 4 && entry[i].bit != 0) /* 0 is out of standard but acceptable */ continue; /* unsupported */ } else { continue; /* unsupported */ } if (entry[i].planes != 1 && entry[i].planes != 0) /* 0 is out of standard but acceptable */ continue; /* unsupported */ if (fzseek(f, entry[i].offset, SEEK_SET)!=0) goto out_entry; if (icon_bitmap_header_read(f, &bitmap_header) != 0) goto out_entry; if (colors == 256) { if (bitmap_header.bit != 8) continue; /* unsupported */ } else if (colors == 16) { if (bitmap_header.bit != 4) continue; /* unsupported */ } if (bitmap_header.planes != 1) continue; /* unsupported */ if (bitmap_header.compression != 0) continue; /* unsupported */ for(j=0;j<colors;++j) { struct icon_rgb_t color; if (icon_rgb_read(f, &color) != 0) goto out_entry; rgb[j].red = color.red; rgb[j].green = color.green; rgb[j].blue = color.blue; } *rgb_max = colors; bitmap = adv_bitmap_alloc(entry[i].width, entry[i].height, 1); if (!bitmap) goto out_entry; *bitmap_mask = adv_bitmap_alloc(entry[i].width, entry[i].height, 1); if (!*bitmap_mask) goto out_bitmap; if (colors == 256) { /* read bitmap xor data (8 bit per pixel) */ for(y=0;y<bitmap->size_y;++y) { unsigned char* line = adv_bitmap_line(bitmap, bitmap->size_y - y - 1); if (fzread(line, bitmap->size_x*bitmap->bytes_per_pixel, 1, f)!=1) goto out_bitmap_mask; } } else if (colors == 16) { /* read bitmap xor data (4 bit per pixel) */ for(y=0;y<bitmap->size_y;++y) { int k; unsigned char* line = adv_bitmap_line(bitmap, bitmap->size_y - y - 1); if (fzread(line, bitmap->size_x / 2, 1, f)!=1) goto out_bitmap_mask; /* convert */ for(k=bitmap->size_x-1;k>=0;--k) { if (k & 1) line[k] = line[k/2] & 0xF; else line[k] = line[k/2] >> 4; } } } /* read bitmap mask data (1 bit per pixel) */ for(y=0;y<bitmap->size_y;++y) { unsigned x ; unsigned char* line = adv_bitmap_line(*bitmap_mask, bitmap->size_y - y - 1); x = 0; while (x < bitmap->size_x) { unsigned bc; int b = fzgetc(f); if (b==EOF) goto out_bitmap_mask; if (x + 8 > bitmap->size_x) bc = bitmap->size_x - x; /* waste unused bit */ else bc = 8; x += bc; while (bc) { if (b & 0x80) *line = 0; else *line = 1; b = b << 1; ++line; --bc; } } } free(entry); return bitmap; } goto out_entry; out_bitmap_mask: adv_bitmap_free(*bitmap_mask); out_bitmap: adv_bitmap_free(bitmap); out_entry: free(entry); out: return 0; }