/* basically an add/subtract function with clamping */ static rgb_t jal_blend_func(rgb_t dest, rgb_t addMe, UINT8 alpha) { int r = (float)RGB_RED (addMe) ; int g = (float)RGB_GREEN(addMe) ; int b = (float)RGB_BLUE (addMe) ; int rd = (float)RGB_RED (dest) ; int gd = (float)RGB_GREEN(dest) ; int bd = (float)RGB_BLUE (dest) ; int finalR, finalG, finalB ; int subR = (alpha & 0x04) >> 2 ; int subG = (alpha & 0x02) >> 1 ; int subB = (alpha & 0x01) ; if (subR) finalR = rd - r ; else finalR = rd + r ; if (finalR < 0) finalR = 0 ; else if (finalR > 255) finalR = 255 ; if (subG) finalG = gd - g ; else finalG = gd + g ; if (finalG < 0) finalG = 0 ; else if (finalG > 255) finalG = 255 ; if (subB) finalB = bd - b ; else finalB = bd + b ; if (finalB < 0) finalB = 0 ; else if (finalB > 255) finalB = 255 ; return MAKE_RGB((UINT8)finalR,(UINT8)finalG,(UINT8)finalB) ; }
void palette_normalize_range(palette_t *palette, UINT32 start, UINT32 end, int lum_min, int lum_max) { UINT32 ymin = 1000 * 255, ymax = 0; UINT32 tmin, tmax; UINT32 index; /* clamp within range */ start = MAX(start, 0); end = MIN(end, palette->numcolors - 1); /* find the minimum and maximum brightness of all the colors in the range */ for (index = start; index <= end; index++) { rgb_t rgb = palette->entry_color[index]; UINT32 y = 299 * RGB_RED(rgb) + 587 * RGB_GREEN(rgb) + 114 * RGB_BLUE(rgb); ymin = MIN(ymin, y); ymax = MAX(ymax, y); } /* determine target minimum/maximum */ tmin = (lum_min < 0) ? ((ymin + 500) / 1000) : lum_min; tmax = (lum_max < 0) ? ((ymax + 500) / 1000) : lum_max; /* now normalize the palette */ for (index = start; index <= end; index++) { rgb_t rgb = palette->entry_color[index]; UINT32 y = 299 * RGB_RED(rgb) + 587 * RGB_GREEN(rgb) + 114 * RGB_BLUE(rgb); UINT32 target = tmin + ((y - ymin) * (tmax - tmin + 1)) / (ymax - ymin); UINT8 r = (y == 0) ? 0 : rgb_clamp(RGB_RED(rgb) * 1000 * target / y); UINT8 g = (y == 0) ? 0 : rgb_clamp(RGB_GREEN(rgb) * 1000 * target / y); UINT8 b = (y == 0) ? 0 : rgb_clamp(RGB_BLUE(rgb) * 1000 * target / y); palette_entry_set_color(palette, index, MAKE_RGB(r, g, b)); } }
INLINE void map_attr_to_fg_bg(unsigned char attr, rgb_t *fg, rgb_t *bg) { *bg = MAKE_ARGB(0xff,0xff,0xff,0xff); *fg = MAKE_ARGB(0xff,0x00,0x00,0x00); if(attr & DCA_ANCILLARY) *bg = MAKE_ARGB(0xff,0xe0,0xe0,0xe0); if(attr & DCA_SELECTED) { *bg = MAKE_ARGB(0xff,0xff,0x80,0x80); } if(attr & DCA_CURRENT) { *bg = MAKE_ARGB(0xff,0xff,0xff,0x00); } if(attr & DCA_CHANGED) { *fg = MAKE_ARGB(0xff,0xff,0x00,0x00); } if(attr & DCA_INVALID) { *fg = MAKE_ARGB(0xff,0x00,0x00,0xff); } if(attr & DCA_DISABLED) { *fg = MAKE_ARGB(RGB_ALPHA(*fg), (RGB_RED(*fg)+RGB_RED(*bg)) >> 1, (RGB_GREEN(*fg)+RGB_GREEN(*bg)) >> 1, (RGB_BLUE(*fg)+RGB_BLUE(*bg)) >> 1); }
static PALETTE_INIT( wolfpack ) { int i; palette_set_color(machine, 0, MAKE_RGB(0x00, 0x00, 0x00)); palette_set_color(machine, 1, MAKE_RGB(0xc1, 0xc1, 0xc1)); palette_set_color(machine, 2, MAKE_RGB(0x81, 0x81, 0x81)); palette_set_color(machine, 3, MAKE_RGB(0x48, 0x48, 0x48)); for (i = 0; i < 4; i++) { rgb_t color = palette_get_color(machine, i); palette_set_color_rgb(machine, 4 + i, RGB_RED(color) < 0xb8 ? RGB_RED(color) + 0x48 : 0xff, RGB_GREEN(color) < 0xb8 ? RGB_GREEN(color) + 0x48 : 0xff, RGB_BLUE(color) < 0xb8 ? RGB_BLUE(color) + 0x48 : 0xff); } colortable[0] = 0; colortable[1] = 1; colortable[2] = 1; colortable[3] = 0; colortable[4] = 0; colortable[5] = 2; colortable[6] = 0; colortable[7] = 3; }
/* basically an add/subtract function with clamping */ rgb_t jal_blend_func(rgb_t dest, rgb_t addMe, UINT8 alpha) { int r, g, b; int ir, ig, ib; r = (int)RGB_RED (dest); g = (int)RGB_GREEN(dest); b = (int)RGB_BLUE (dest); ir = (int)RGB_RED (addMe); ig = (int)RGB_GREEN(addMe); ib = (int)RGB_BLUE (addMe); if (alpha & 4) { r -= ir; if (r < 0) r = 0; } else { r += ir; if (r > 255) r = 255; } if (alpha & 2) { g -= ig; if (g < 0) g = 0; } else { g += ig; if (g > 255) g = 255; } if (alpha & 1) { b -= ib; if (b < 0) b = 0; } else { b += ib; if (b > 255) b = 255; } return MAKE_RGB(r,g,b); }
UINT32 speglsht_state::screen_update_speglsht(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { int x,y,dy; dy=(m_videoreg&0x20)?(256*512):0; //visible frame for(y=0;y<256;y++) { for(x=0;x<512;x++) { int tmp=dy+y*512+x; PLOT_PIXEL_RGB(x-67,y-5,(m_framebuffer[tmp]>>0)&0xff,(m_framebuffer[tmp]>>8)&0xff,(m_framebuffer[tmp]>>16)&0xff); } } //draw st0016 gfx to temporary bitmap (indexed 16) m_bitmap->fill(0); st0016_draw_screen(screen, *m_bitmap, cliprect); //copy temporary bitmap to rgb 32 bit bitmap for(y=cliprect.min_y; y<cliprect.max_y;y++) { UINT16 *srcline = &m_bitmap->pix16(y); for(x=cliprect.min_x; x<cliprect.max_x;x++) { if(srcline[x]) { rgb_t color=palette_get_color(machine(), srcline[x]); PLOT_PIXEL_RGB(x,y,RGB_RED(color),RGB_GREEN(color),RGB_BLUE(color)); } } } return 0; }
INLINE rgb_t adjust_palette_entry(rgb_t entry, float brightness, float contrast, const UINT8 *gamma_map) { int r = rgb_clamp((float)gamma_map[RGB_RED(entry)] * contrast + brightness); int g = rgb_clamp((float)gamma_map[RGB_GREEN(entry)] * contrast + brightness); int b = rgb_clamp((float)gamma_map[RGB_BLUE(entry)] * contrast + brightness); int a = RGB_ALPHA(entry); return MAKE_ARGB(a,r,g,b); }
void GradientFillH(HDC hdc, long x1, long y1, long x2, long y2, COLORREF c1, COLORREF c2) { TRIVERTEX vert[3] ; GRADIENT_RECT gRect; vert [0] .x = x1; vert [0] .y = y1; vert [0] .Red = RGB_RED(c1) << 8; vert [0] .Green = RGB_GREEN(c1) << 8; vert [0] .Blue = RGB_BLUE(c1) << 8; vert [0] .Alpha = 0x0000; vert [1] .x = x2; vert [1] .y = y2; vert [1] .Red = RGB_RED(c2) << 8; vert [1] .Green = RGB_GREEN(c2) << 8; vert [1] .Blue = RGB_BLUE(c2) << 8; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hdc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_H); }
void m62_state::m62_amplify_contrast(palette_t *palette, UINT32 numcolors) { // m62 palette is very dark, so amplify default contrast UINT32 i, ymax=1; if (!numcolors) numcolors = palette_get_num_colors(palette); // find maximum brightness for (i=0;i < numcolors;i++) { rgb_t rgb = palette_entry_get_color(palette,i); UINT32 y = 299 * RGB_RED(rgb) + 587 * RGB_GREEN(rgb) + 114 * RGB_BLUE(rgb); ymax = MAX(ymax, y); } palette_set_contrast(palette, 255000.0/ymax); }
static SCREEN_UPDATE(speglsht) { speglsht_state *state = screen->machine().driver_data<speglsht_state>(); int x,y,dy; dy=(state->m_videoreg&0x20)?(256*512):0; //visible frame for(y=0;y<256;y++) { for(x=0;x<512;x++) { int tmp=dy+y*512+x; PLOT_PIXEL_RGB(x-67,y-5,(state->m_framebuffer[tmp]>>0)&0xff,(state->m_framebuffer[tmp]>>8)&0xff,(state->m_framebuffer[tmp]>>16)&0xff); } } //draw st0016 gfx to temporary bitmap (indexed 16) bitmap_fill(state->m_bitmap,NULL,0); st0016_draw_screen(screen, state->m_bitmap, cliprect); //copy temporary bitmap to rgb 32 bit bitmap for(y=cliprect->min_y; y<cliprect->max_y;y++) { UINT16 *srcline = BITMAP_ADDR16(state->m_bitmap, y, 0); for(x=cliprect->min_x; x<cliprect->max_x;x++) { if(srcline[x]) { rgb_t color=palette_get_color(screen->machine(), srcline[x]); PLOT_PIXEL_RGB(x,y,RGB_RED(color),RGB_GREEN(color),RGB_BLUE(color)); } } } return 0; }
static void lcd_test(cyg_addrword_t p) { int i, pix, row, col; int on; diag_printf("LCD test here\n"); lcd_init(16); #if 0 for (i = 0; i < 16; i++) { on = true; diag_printf("Fill with 0x%x\n", i); for (row = 0; row < 240; row++) { for (col = 0; col < 320/2; col++) { if (on) { fp->pixels[row][col] = RGB_RED(i)|RGB_GREEN(i)|RGB_BLUE(i); } else { fp->pixels[row][col] = 0xFFFF; } } for (col = 320/2; col < 320; col++) { if (!on) { fp->pixels[row][col] = RGB_RED(i)|RGB_GREEN(i)|RGB_BLUE(i); } else { fp->pixels[row][col] = 0xFFFF; } } if ((row & 0x0F) == 0x0F) { if (on) { on = false; } else { on = true; } } } cyg_thread_delay(100); } #endif #if 0 for (i = 0; i < 4; i++) { for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { switch (row/40) { case 0: pix = col / 20; // 0..15 fp->pixels[row][col] = RGB_RED(pix); break; case 1: pix = col / 10; // 0..31 fp->pixels[row][col] = RGB_GREEN(pix); break; case 2: pix = col / 20; // 0..15 fp->pixels[row][col] = RGB_BLUE(pix); break; case 3: pix = col / 20; // 0..15 fp->pixels[row][col] = RGB_BLUE(pix) | RGB_GREEN(pix); break; case 4: pix = col / 20; // 0..15 fp->pixels[row][col] = RGB_BLUE(15) | RGB_GREEN(pix); break; case 5: fp->pixels[row][col] = 0xFFFF; break; } } } cyg_thread_delay(100); #if 0 for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { pix = col / 20; // 0..15 switch (row/60) { case 0: fp->pixels[row][col] = RGB_RED(pix); break; case 1: fp->pixels[row][col] = RGB_GREEN(pix); break; case 2: fp->pixels[row][col] = RGB_BLUE(pix); break; case 3: fp->pixels[row][col] = 0xFFFF; break; } } } cyg_thread_delay(100); #endif #if 0 on = true; for (row = 0; row < 240; row++) { for (col = 0; col < 320/2; col++) { if (on) { fp->pixels[row][col] = RGB_GREEN(15); } else { fp->pixels[row][col] = RGB_BLUE(8); } } for (col = 320/2; col < 320; col++) { if (!on) { fp->pixels[row][col] = RGB_GREEN(15); } else { fp->pixels[row][col] = RGB_BLUE(8); } } if ((row & 0x0F) == 0x0F) { if (on) { on = false; } else { on = true; } } } #endif } #endif #if 0 for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { if (col == 59) { fp->pixels[row][col] = 0x0000; } else { fp->pixels[row][col] = 0xFFFF; } } } cyg_thread_delay(100); #endif #if 0 for (i = 0; i < 16; i++) { diag_printf("Value 0x%04x\n", (1<<i)); for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { fp->pixels[row][col] = (1<<i); } } cyg_thread_delay(500); } #endif #if 0 for (i = 0; i < 32; i++) { diag_printf("Red at %d\n", i); for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { fp->pixels[row][col] = RGB_RED(i); } } cyg_thread_delay(100); } #endif #if 0 for (i = 0; i < 64; i++) { diag_printf("Green at %d\n", i); for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { fp->pixels[row][col] = RGB_GREEN(i); } } cyg_thread_delay(100); } #endif #if 0 for (i = 0; i < 32; i++) { diag_printf("BLUE at %d\n", i); for (row = 0; row < 240; row++) { for (col = 0; col < 320; col++) { fp->pixels[row][col] = RGB_BLUE(i); } } cyg_thread_delay(100); } #endif while (true) { for (i = 0; i < 1; i++) { show_xpm(redboot_xpm); cyg_thread_delay(15); show_xpm(eCos_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(15); show_xpm(redhat_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(15); show_xpm(escw_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(15); show_xpm(eCos2_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(15); show_xpm(redhat2_xpm); cyg_thread_delay(25); show_xpm(logo_xpm); cyg_thread_delay(25); show_xpm(redboot_xpm); cyg_thread_delay(50); } #if 0 // This doesn't seem to do anything on my unit assabet_BCR(SA1110_BCR_MOTOR, SA1110_BCR_MOTOR_ON); cyg_thread_delay(2*100); assabet_BCR(SA1110_BCR_MOTOR, SA1110_BCR_MOTOR_OFF); #endif show_xpm(redboot_xpm); cyg_thread_delay(15); lcd_clear(); lcd_printf("\n\n**** Hello world!\n"); cyg_thread_delay(5); for (i = 0; i < 64; i++) { lcd_printf("... testing line #%d\n", i); } cyg_thread_delay(50); show_xpm(redboot_xpm); cyg_thread_delay(15); set_bg(0,0,0); set_fg(31,63,0); lcd_clear(); for (i = 0; i < 32; i++) { lcd_printf("... testing line #%d\n", i); } cyg_thread_delay(50); } // while lcd_clear(); lcd_printf("*****"); cyg_thread_delay(200); cyg_test_exit(); }
void ui_menu::draw(bool customonly) { float line_height = ui_get_line_height(machine()); float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); float ud_arrow_width = line_height * machine().render().ui_aspect(); float gutter_width = lr_arrow_width * 1.3f; float x1, y1, x2, y2; float effective_width, effective_left; float visible_width, visible_main_menu_height; float visible_extra_menu_height = 0; float visible_top, visible_left; int selected_subitem_too_big = FALSE; int visible_lines; int top_line; int itemnum, linenum; int mouse_hit, mouse_button; render_target *mouse_target; INT32 mouse_target_x, mouse_target_y; float mouse_x = -1, mouse_y = -1; /* compute the width and height of the full menu */ visible_width = 0; visible_main_menu_height = 0; for (itemnum = 0; itemnum < numitems; itemnum++) { const ui_menu_item &pitem = item[itemnum]; float total_width; /* compute width of left hand side */ total_width = gutter_width + ui_get_string_width(machine(), pitem.text) + gutter_width; /* add in width of right hand side */ if (pitem.subtext) total_width += 2.0f * gutter_width + ui_get_string_width(machine(), pitem.subtext); /* track the maximum */ if (total_width > visible_width) visible_width = total_width; /* track the height as well */ visible_main_menu_height += line_height; } /* account for extra space at the top and bottom */ visible_extra_menu_height = customtop + custombottom; /* add a little bit of slop for rounding */ visible_width += 0.01f; visible_main_menu_height += 0.01f; /* if we are too wide or too tall, clamp it down */ if (visible_width + 2.0f * UI_BOX_LR_BORDER > 1.0f) visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER; /* if the menu and extra menu won't fit, take away part of the regular menu, it will scroll */ if (visible_main_menu_height + visible_extra_menu_height + 2.0f * UI_BOX_TB_BORDER > 1.0f) visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height; visible_lines = floor(visible_main_menu_height / line_height); visible_main_menu_height = (float)visible_lines * line_height; /* compute top/left of inner menu area by centering */ visible_left = (1.0f - visible_width) * 0.5f; visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; /* if the menu is at the bottom of the extra, adjust */ visible_top += customtop; /* first add us a box */ x1 = visible_left - UI_BOX_LR_BORDER; y1 = visible_top - UI_BOX_TB_BORDER; x2 = visible_left + visible_width + UI_BOX_LR_BORDER; y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER; if (!customonly) ui_draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); /* determine the first visible line based on the current selection */ top_line = selected - visible_lines / 2; if (top_line < 0) top_line = 0; if (top_line + visible_lines >= numitems) top_line = numitems - visible_lines; /* determine effective positions taking into account the hilighting arrows */ effective_width = visible_width - 2.0f * gutter_width; effective_left = visible_left + gutter_width; /* locate mouse */ mouse_hit = FALSE; mouse_button = FALSE; if (!customonly) { mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button); if (mouse_target != NULL) if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y)) mouse_hit = TRUE; } /* loop over visible lines */ hover = numitems + 1; if (!customonly) for (linenum = 0; linenum < visible_lines; linenum++) { float line_y = visible_top + (float)linenum * line_height; itemnum = top_line + linenum; const ui_menu_item &pitem = item[itemnum]; const char *itemtext = pitem.text; rgb_t fgcolor = UI_TEXT_COLOR; rgb_t bgcolor = UI_TEXT_BG_COLOR; rgb_t fgcolor2 = UI_SUBITEM_COLOR; rgb_t fgcolor3 = UI_CLONE_COLOR; float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; float line_y0 = line_y; float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; float line_y1 = line_y + line_height; /* set the hover if this is our item */ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable()) hover = itemnum; /* if we're selected, draw with a different background */ if (itemnum == selected) { #ifdef UI_COLOR_DISPLAY rgb_t fgcolor0 = ui_get_rgb_color(CURSOR_SELECTED_TEXT); rgb_t bgcolor0 = ui_get_rgb_color(CURSOR_SELECTED_BG); fgcolor = MAKE_ARGB(0xe0, RGB_RED(fgcolor0), RGB_GREEN(fgcolor0), RGB_BLUE(fgcolor0)); bgcolor = MAKE_ARGB(0xe0, RGB_RED(bgcolor0), RGB_GREEN(bgcolor0), RGB_BLUE(bgcolor0)); #else /* UI_COLOR_DISPLAY */ fgcolor = UI_SELECTED_COLOR; bgcolor = UI_SELECTED_BG_COLOR; #endif /* UI_COLOR_DISPLAY */ fgcolor2 = UI_SELECTED_COLOR; fgcolor3 = UI_SELECTED_COLOR; } /* else if the mouse is over this item, draw with a different background */ else if (itemnum == hover) { #ifdef UI_COLOR_DISPLAY rgb_t fgcolor0 = ui_get_rgb_color(CURSOR_HOVER_TEXT); rgb_t bgcolor0 = ui_get_rgb_color(CURSOR_HOVER_BG); fgcolor = MAKE_ARGB(0xe0, RGB_RED(fgcolor0), RGB_GREEN(fgcolor0), RGB_BLUE(fgcolor0)); bgcolor = MAKE_ARGB(0xe0, RGB_RED(bgcolor0), RGB_GREEN(bgcolor0), RGB_BLUE(bgcolor0)); #else /* UI_COLOR_DISPLAY */ fgcolor = UI_MOUSEOVER_COLOR; bgcolor = UI_MOUSEOVER_BG_COLOR; #endif /* UI_COLOR_DISPLAY */ fgcolor2 = UI_MOUSEOVER_COLOR; fgcolor3 = UI_MOUSEOVER_COLOR; } /* if we have some background hilighting to do, add a quad behind everything else */ if (bgcolor != UI_TEXT_BG_COLOR) container->add_quad(line_x0, line_y0, line_x1, line_y1, bgcolor, hilight_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); /* if we're on the top line, display the up arrow */ if (linenum == 0 && top_line != 0) { container->add_quad( 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT0)); if (hover == itemnum) hover = -2; } /* if we're on the bottom line, display the down arrow */ else if (linenum == visible_lines - 1 && itemnum != numitems - 1) { container->add_quad( 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT0 ^ ORIENTATION_FLIP_Y)); if (hover == itemnum) hover = -1; } /* if we're just a divider, draw a line */ else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0) container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); /* if we don't have a subitem, just draw the string centered */ else if (pitem.subtext == NULL) ui_draw_text_full(container, itemtext, effective_left, line_y, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, NULL, NULL); /* otherwise, draw the item on the left and the subitem text on the right */ else { int subitem_invert = pitem.flags & MENU_FLAG_INVERT; const char *subitem_text = pitem.subtext; float item_width, subitem_width; /* draw the left-side text */ ui_draw_text_full(container, itemtext, effective_left, line_y, effective_width, JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, &item_width, NULL); /* give 2 spaces worth of padding */ item_width += 2.0f * gutter_width; /* if the subitem doesn't fit here, display dots */ if (ui_get_string_width(machine(), subitem_text) > effective_width - item_width) { subitem_text = "..."; if (itemnum == selected) selected_subitem_too_big = TRUE; } /* draw the subitem right-justified */ ui_draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width, JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, subitem_invert ? fgcolor3 : fgcolor2, bgcolor, &subitem_width, NULL); /* apply arrows */ if (itemnum == selected && (pitem.flags & MENU_FLAG_LEFT_ARROW)) { container->add_quad( effective_left + effective_width - subitem_width - gutter_width, line_y + 0.1f * line_height, effective_left + effective_width - subitem_width - gutter_width + lr_arrow_width, line_y + 0.9f * line_height, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X)); } if (itemnum == selected && (pitem.flags & MENU_FLAG_RIGHT_ARROW)) { container->add_quad( effective_left + effective_width + gutter_width - lr_arrow_width, line_y + 0.1f * line_height, effective_left + effective_width + gutter_width, line_y + 0.9f * line_height, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90)); } } } /* if the selected subitem is too big, display it in a separate offset box */ if (selected_subitem_too_big) { const ui_menu_item &pitem = item[selected]; int subitem_invert = pitem.flags & MENU_FLAG_INVERT; linenum = selected - top_line; float line_y = visible_top + (float)linenum * line_height; float target_width, target_height; float target_x, target_y; /* compute the multi-line target width/height */ ui_draw_text_full(container, pitem.subtext, 0, 0, visible_width * 0.75f, JUSTIFY_RIGHT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height); /* determine the target location */ target_x = visible_left + visible_width - target_width - UI_BOX_LR_BORDER; target_y = line_y + line_height + UI_BOX_TB_BORDER; if (target_y + target_height + UI_BOX_TB_BORDER > visible_main_menu_height) target_y = line_y - target_height - UI_BOX_TB_BORDER; /* add a box around that */ ui_draw_outlined_box(container, target_x - UI_BOX_LR_BORDER, target_y - UI_BOX_TB_BORDER, target_x + target_width + UI_BOX_LR_BORDER, target_y + target_height + UI_BOX_TB_BORDER, subitem_invert ? UI_SELECTED_BG_COLOR : UI_BACKGROUND_COLOR); ui_draw_text_full(container, pitem.subtext, target_x, target_y, target_width, JUSTIFY_RIGHT, WRAP_WORD, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, NULL, NULL); } /* if there is something special to add, do it by calling the virtual method */ custom_render((selected >= 0 && selected < numitems) ? item[selected].ref : NULL, customtop, custombottom, x1, y1, x2, y2); /* return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow */ visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != numitems); }