summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2010-10-18 01:51:58 +0000
committer Aaron Giles <aaron@aarongiles.com>2010-10-18 01:51:58 +0000
commitd8edbd14f2df73ca8d990dd5f93687b369374953 (patch)
tree447102b241ab9c5c66d85baffdb131dfb83a6535 /src
parentd73bcf6e1c99f4c1f5f5790d803d3fcf5100d29b (diff)
Convert rendlay objects into C++, reduce the number of unused textures
allocated. Fix texture leak in crsshair.c.
Diffstat (limited to 'src')
-rw-r--r--src/emu/crsshair.c14
-rw-r--r--src/emu/emucore.h2
-rw-r--r--src/emu/render.c348
-rw-r--r--src/emu/render.h150
-rw-r--r--src/emu/rendlay.c2558
-rw-r--r--src/emu/rendlay.h443
-rw-r--r--src/emu/rendutil.c10
-rw-r--r--src/emu/rendutil.h2
-rw-r--r--src/emu/video.c36
-rw-r--r--src/emu/video.h2
-rw-r--r--src/osd/windows/video.h4
-rw-r--r--src/osd/windows/window.c3
-rw-r--r--src/osd/windows/window.h2
13 files changed, 1773 insertions, 1801 deletions
diff --git a/src/emu/crsshair.c b/src/emu/crsshair.c
index efa031a7b93..58493fb5e78 100644
--- a/src/emu/crsshair.c
+++ b/src/emu/crsshair.c
@@ -154,8 +154,9 @@ static void create_bitmap(running_machine *machine, int player)
char filename[20];
rgb_t color = crosshair_colors[player];
- /* if we have a bitmap for this player, kill it */
+ /* if we have a bitmap and texture for this player, kill it */
global_free(global.bitmap[player]);
+ machine->render().texture_free(global.texture[player]);
if (global.name[player][0] != 0)
{
@@ -208,9 +209,6 @@ static void create_bitmap(running_machine *machine, int player)
void crosshair_init(running_machine *machine)
{
- const input_port_config *port;
- const input_field_config *field;
-
/* request a callback upon exiting */
machine->add_notifier(MACHINE_NOTIFY_EXIT, crosshair_exit);
@@ -221,8 +219,8 @@ void crosshair_init(running_machine *machine)
global.auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
/* determine who needs crosshairs */
- for (port = machine->m_portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
+ for (const input_port_config *port = machine->m_portlist.first(); port != NULL; port = port->next())
+ for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
if (field->crossaxis != CROSSHAIR_AXIS_NONE)
{
int player = field->player;
@@ -258,10 +256,8 @@ void crosshair_init(running_machine *machine)
static void crosshair_exit(running_machine &machine)
{
- int player;
-
/* free bitmaps and textures for each player */
- for (player = 0; player < MAX_PLAYERS; player++)
+ for (int player = 0; player < MAX_PLAYERS; player++)
{
machine.render().texture_free(global.texture[player]);
global.texture[player] = NULL;
diff --git a/src/emu/emucore.h b/src/emu/emucore.h
index 417739dc391..71881cf8ac9 100644
--- a/src/emu/emucore.h
+++ b/src/emu/emucore.h
@@ -374,6 +374,8 @@ public:
m_count(0) { }
virtual ~simple_list() { reset(); }
+
+ resource_pool &pool() const { return m_pool; }
T *first() const { return m_head; }
T *last() const { return m_tail; }
diff --git a/src/emu/render.c b/src/emu/render.c
index f0eee33ae90..48bc9fcdfe4 100644
--- a/src/emu/render.c
+++ b/src/emu/render.c
@@ -201,21 +201,19 @@ inline void normalize_bounds(render_bounds &bounds)
// appropriate layer index and blendmode
//-------------------------------------------------
-inline int get_layer_and_blendmode(const layout_view &view, int index, int &blendmode)
+inline item_layer get_layer_and_blendmode(const layout_view &view, int index, int &blendmode)
{
- const int *layer_order = layer_order_standard;
- int layer;
-
// if we have multiple backdrop pieces and no overlays, render:
// backdrop (add) + screens (add) + bezels (alpha)
// else render:
// screens (add) + overlays (RGB multiply) + backdrop (add) + bezels (alpha)
- if (view.itemlist[ITEM_LAYER_BACKDROP] != NULL && view.itemlist[ITEM_LAYER_BACKDROP]->next != NULL && view.itemlist[ITEM_LAYER_OVERLAY] == NULL)
+ const int *layer_order = layer_order_standard;
+ if (view.first_item(ITEM_LAYER_BACKDROP) != NULL && view.first_item(ITEM_LAYER_BACKDROP)->next() != NULL && view.first_item(ITEM_LAYER_OVERLAY) == NULL)
layer_order = layer_order_alternate;
// select the layer
- layer = layer_order[index];
+ int layer = layer_order[index];
// pick a blendmode
if (layer == ITEM_LAYER_SCREEN && layer_order == layer_order_standard)
@@ -227,7 +225,7 @@ inline int get_layer_and_blendmode(const layout_view &view, int index, int &blen
else
blendmode = BLENDMODE_ALPHA;
- return layer;
+ return item_layer(layer);
}
@@ -1025,7 +1023,7 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
: m_next(NULL),
m_manager(manager),
m_curview(NULL),
- m_filelist(NULL),
+ m_filelist(*auto_alloc(&manager.machine(), simple_list<layout_file>(manager.machine().m_respool))),
m_flags(flags),
m_listindex(0),
m_width(640),
@@ -1033,19 +1031,17 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
m_pixel_aspect(0.0f),
m_max_refresh(0),
m_orientation(0),
- m_layerconfig(LAYER_CONFIG_DEFAULT),
m_base_view(NULL),
m_base_orientation(ROT0),
- m_base_layerconfig(LAYER_CONFIG_DEFAULT),
m_maxtexwidth(65536),
m_maxtexheight(65536),
m_debug_containers(manager.machine().m_respool)
{
// determine the base layer configuration based on options
- if (!options_get_bool(manager.machine().options(), OPTION_USE_BACKDROPS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_BACKDROP;
- if (!options_get_bool(manager.machine().options(), OPTION_USE_OVERLAYS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_OVERLAY;
- if (!options_get_bool(manager.machine().options(), OPTION_USE_BEZELS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_BEZEL;
- if (options_get_bool(manager.machine().options(), OPTION_ARTWORK_CROP)) m_base_layerconfig |= LAYER_CONFIG_ZOOM_TO_SCREEN;
+ m_base_layerconfig.set_backdrops_enabled(options_get_bool(manager.machine().options(), OPTION_USE_BACKDROPS));
+ m_base_layerconfig.set_overlays_enabled(options_get_bool(manager.machine().options(), OPTION_USE_OVERLAYS));
+ m_base_layerconfig.set_bezels_enabled(options_get_bool(manager.machine().options(), OPTION_USE_BEZELS));
+ m_base_layerconfig.set_zoom_to_screen(options_get_bool(manager.machine().options(), OPTION_ARTWORK_CROP));
// determine the base orientation based on options
m_orientation = ROT0;
@@ -1086,13 +1082,7 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
render_target::~render_target()
{
- // free the layout files
- while (m_filelist != NULL)
- {
- layout_file *temp = m_filelist;
- m_filelist = temp->next;
- layout_file_free(temp);
- }
+ auto_free(&m_manager.machine(), &m_filelist);
}
@@ -1134,18 +1124,6 @@ void render_target::set_bounds(INT32 width, INT32 height, float pixel_aspect)
//-------------------------------------------------
-// set_layer_config - set the layer config of a
-// target
-//-------------------------------------------------
-
-void render_target::set_layer_config(int layerconfig)
-{
- m_layerconfig = layerconfig;
- layout_view_recompute(m_curview, layerconfig);
-}
-
-
-//-------------------------------------------------
// set_view - dynamically change the view for
// a target
//-------------------------------------------------
@@ -1156,7 +1134,7 @@ void render_target::set_view(int viewindex)
if (view != NULL)
{
m_curview = view;
- layout_view_recompute(view, m_layerconfig);
+ view->recompute(m_layerconfig);
}
}
@@ -1180,7 +1158,7 @@ void render_target::set_max_texture_size(int maxwidth, int maxheight)
const char *render_target::view_name(int viewindex)
{
layout_view *view = view_by_index(viewindex);
- return (view != NULL) ? view->name : NULL;
+ return (view != NULL) ? view->name() : NULL;
}
@@ -1190,10 +1168,10 @@ const char *render_target::view_name(int viewindex)
// given view
//-------------------------------------------------
-UINT32 render_target::view_screens(int viewindex)
+const render_screen_list &render_target::view_screens(int viewindex)
{
layout_view *view = view_by_index(viewindex);
- return (view != NULL) ? view->screens : NULL;
+ return (view != NULL) ? view->screens() : s_empty_screen_list;
}
@@ -1212,7 +1190,7 @@ void render_target::compute_visible_area(INT32 target_width, INT32 target_height
if (target_pixel_aspect != 0.0f)
{
// start with the aspect ratio of the square pixel layout
- width = (zoom_to_screen() && m_curview->screens > 0) ? m_curview->scraspect : m_curview->aspect;
+ width = m_curview->effective_aspect(m_layerconfig);
height = 1.0f;
// first apply target orientation
@@ -1254,44 +1232,43 @@ void render_target::compute_minimum_size(INT32 &minwidth, INT32 &minheight)
{
float maxxscale = 1.0f, maxyscale = 1.0f;
int screens_considered = 0;
+
+ // early exit in case we are called between device teardown and render teardown
+ if (m_manager.machine().m_devicelist.count() == 0)
+ {
+ minwidth = 640;
+ minheight = 480;
+ return;
+ }
// scan the current view for all screens
- for (int layer = 0; layer < ITEM_LAYER_MAX; layer++)
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
// iterate over items in the layer
- for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
- if (item->element == NULL)
+ for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
+ if (curitem->screen() != NULL)
{
- const screen_device_config *scrconfig = downcast<const screen_device_config *>(m_manager.machine().config->m_devicelist.find(SCREEN, item->index));
- screen_device *screendev = m_manager.machine().device<screen_device>(scrconfig->tag());
-
- // we may be called very early, before machine->visible_area is initialized; handle that case
+ // use a hard-coded default visible area for vector screens
+ screen_device *screen = curitem->screen();
const rectangle vectorvis = { 0, 639, 0, 479 };
- const rectangle *visarea = NULL;
- if (scrconfig->screen_type() == SCREEN_TYPE_VECTOR)
- visarea = &vectorvis;
- else if (screendev != NULL && screendev->started())
- visarea = &screendev->visible_area();
- else
- visarea = &scrconfig->visible_area();
+ const rectangle &visarea = (screen->screen_type() == SCREEN_TYPE_VECTOR) ? vectorvis : screen->visible_area();
// apply target orientation to the bounds
- render_bounds bounds = item->bounds;
+ render_bounds bounds = curitem->bounds();
apply_orientation(bounds, m_orientation);
normalize_bounds(bounds);
// based on the orientation of the screen container, check the bitmap
- render_container *container = m_manager.m_screen_container_list.find(item->index);
float xscale, yscale;
- if (!(orientation_add(m_orientation, container->orientation()) & ORIENTATION_SWAP_XY))
+ if (!(orientation_add(m_orientation, screen->container().orientation()) & ORIENTATION_SWAP_XY))
{
- xscale = (float)(visarea->max_x + 1 - visarea->min_x) / (bounds.x1 - bounds.x0);
- yscale = (float)(visarea->max_y + 1 - visarea->min_y) / (bounds.y1 - bounds.y0);
+ xscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.x1 - bounds.x0);
+ yscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.y1 - bounds.y0);
}
else
{
- xscale = (float)(visarea->max_y + 1 - visarea->min_y) / (bounds.x1 - bounds.x0);
- yscale = (float)(visarea->max_x + 1 - visarea->min_x) / (bounds.y1 - bounds.y0);
+ xscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.x1 - bounds.x0);
+ yscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.y1 - bounds.y0);
}
// pick the greater
@@ -1348,17 +1325,17 @@ render_primitive_list &render_target::get_primitives()
// iterate over layers back-to-front, but only if we're running
if (m_manager.machine().phase() >= MACHINE_PHASE_RESET)
- for (int layernum = 0; layernum < ITEM_LAYER_MAX; layernum++)
+ for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
{
int blendmode;
- int layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
- if (m_curview->layenabled[layer])
+ item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
+ if (m_curview->layer_enabled(layer))
{
// iterate over items in the layer
- for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
+ for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
{
// first apply orientation to the bounds
- render_bounds bounds = item->bounds;
+ render_bounds bounds = curitem->bounds();
apply_orientation(bounds, root_xform.orientation);
normalize_bounds(bounds);
@@ -1368,32 +1345,18 @@ render_primitive_list &render_target::get_primitives()
item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale;
item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale;
item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale;
- item_xform.color.r = item->color.r * root_xform.color.r;
- item_xform.color.g = item->color.g * root_xform.color.g;
- item_xform.color.b = item->color.b * root_xform.color.b;
- item_xform.color.a = item->color.a * root_xform.color.a;
- item_xform.orientation = orientation_add(item->orientation, root_xform.orientation);
+ item_xform.color.r = curitem->color().r * root_xform.color.r;
+ item_xform.color.g = curitem->color().g * root_xform.color.g;
+ item_xform.color.b = curitem->color().b * root_xform.color.b;
+ item_xform.color.a = curitem->color().a * root_xform.color.a;
+ item_xform.orientation = orientation_add(curitem->orientation(), root_xform.orientation);
item_xform.no_center = false;
// if there is no associated element, it must be a screen element
- if (item->element != NULL)
- {
- int state = 0;
- if (item->output_name[0] != 0)
- state = output_get_value(item->output_name);
- else if (item->input_tag[0] != 0)
- {
- const input_field_config *field = input_field_by_tag_and_mask(m_manager.machine().m_portlist, item->input_tag, item->input_mask);
- if (field != NULL)
- state = ((input_port_read_safe(&m_manager.machine(), item->input_tag, 0) ^ field->defvalue) & item->input_mask) ? 1 : 0;
- }
- add_element_primitives(list, item_xform, *item->element, state, blendmode);
- }
+ if (curitem->screen() != NULL)
+ add_container_primitives(list, item_xform, curitem->screen()->container(), blendmode);
else
- {
- render_container *container = m_manager.m_screen_container_list.find(item->index);
- add_container_primitives(list, item_xform, *container, blendmode);
- }
+ add_element_primitives(list, item_xform, *curitem->element(), curitem->state(), blendmode);
}
}
}
@@ -1468,8 +1431,9 @@ render_primitive_list &render_target::get_primitives()
bool render_target::map_point_container(INT32 target_x, INT32 target_y, render_container &container, float &container_x, float &container_y)
{
- view_item *item;
- return map_point_internal(target_x, target_y, &container, container_x, container_y, item);
+ const char *input_tag;
+ UINT32 input_mask;
+ return map_point_internal(target_x, target_y, &container, container_x, container_y, input_tag, input_mask);
}
@@ -1481,15 +1445,7 @@ bool render_target::map_point_container(INT32 target_x, INT32 target_y, render_c
bool render_target::map_point_input(INT32 target_x, INT32 target_y, const char *&input_tag, UINT32 &input_mask, float &input_x, float &input_y)
{
- view_item *item = NULL;
-
- bool result = map_point_internal(target_x, target_y, NULL, input_x, input_y, item);
- if (result && item != NULL)
- {
- input_tag = item->input_tag;
- input_mask = item->input_mask;
- }
- return result;
+ return map_point_internal(target_x, target_y, NULL, input_x, input_y, input_tag, input_mask);
}
@@ -1548,22 +1504,27 @@ void render_target::debug_top(render_container &container)
//-------------------------------------------------
+// update_layer_config - recompute after a layer
+// config change
+//-------------------------------------------------
+
+void render_target::update_layer_config()
+{
+ m_curview->recompute(m_layerconfig);
+}
+
+
+//-------------------------------------------------
// load_layout_files - load layout files for a
// given render target
//-------------------------------------------------
void render_target::load_layout_files(const char *layoutfile, bool singlefile)
{
- layout_file **nextfile = &m_filelist;
-
// if there's an explicit file, load that first
const char *basename = m_manager.machine().basename();
if (layoutfile != NULL)
- {
- *nextfile = layout_file_load(m_manager.machine(), basename, layoutfile);
- if (*nextfile != NULL)
- nextfile = &(*nextfile)->next;
- }
+ load_layout_file(basename, layoutfile);
// if we're only loading this file, we know our final result
if (singlefile)
@@ -1571,51 +1532,96 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
// try to load a file based on the driver name
const game_driver *gamedrv = m_manager.machine().gamedrv;
- *nextfile = layout_file_load(m_manager.machine(), basename, gamedrv->name);
- if (*nextfile == NULL)
- *nextfile = layout_file_load(m_manager.machine(), basename, "default");
- if (*nextfile != NULL)
- nextfile = &(*nextfile)->next;
+ if (!load_layout_file(basename, gamedrv->name))
+ load_layout_file(basename, "default");
// if a default view has been specified, use that as a fallback
if (gamedrv->default_layout != NULL)
- {
- *nextfile = layout_file_load(m_manager.machine(), NULL, gamedrv->default_layout);
- if (*nextfile != NULL)
- nextfile = &(*nextfile)->next;
- }
+ load_layout_file(NULL, gamedrv->default_layout);
if (m_manager.machine().m_config.m_default_layout != NULL)
- {
- *nextfile = layout_file_load(m_manager.machine(), NULL, m_manager.machine().m_config.m_default_layout);
- if (*nextfile != NULL)
- nextfile = &(*nextfile)->next;
- }
+ load_layout_file(NULL, m_manager.machine().m_config.m_default_layout);
// try to load another file based on the parent driver name
const game_driver *cloneof = driver_get_clone(gamedrv);
if (cloneof != NULL)
- {
- *nextfile = layout_file_load(m_manager.machine(), cloneof->name, cloneof->name);
- if (*nextfile == NULL)
- *nextfile = layout_file_load(m_manager.machine(), cloneof->name, "default");
- if (*nextfile != NULL)
- nextfile = &(*nextfile)->next;
- }
+ if (!load_layout_file(cloneof->name, cloneof->name))
+ load_layout_file(cloneof->name, "default");
// now do the built-in layouts for single-screen games
if (screen_count(m_manager.machine().m_config) == 1)
{
if (gamedrv->flags & ORIENTATION_SWAP_XY)
- *nextfile = layout_file_load(m_manager.machine(), NULL, layout_vertical);
+ load_layout_file(NULL, layout_vertical);
else
- *nextfile = layout_file_load(m_manager.machine(), NULL, layout_horizont);
- assert_always(*nextfile != NULL, "Couldn't parse default layout??");
- nextfile = &(*nextfile)->next;
+ load_layout_file(NULL, layout_horizont);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
}
}
//-------------------------------------------------
+// load_layout_file - load a single layout file
+// and append it to our list
+//-------------------------------------------------
+
+bool render_target::load_layout_file(const char *dirname, const char *filename)
+{
+ // if the first character of the "file" is an open brace, assume it is an XML string
+ xml_data_node *rootnode;
+ if (filename[0] == '<')
+ rootnode = xml_string_read(filename, NULL);
+
+ // otherwise, assume it is a file
+ else
+ {
+ // build the path and optionally prepend the directory
+ astring fname(filename, ".lay");
+ if (dirname != NULL)
+ fname.ins(0, PATH_SEPARATOR).ins(0, dirname);
+
+ // attempt to open the file; bail if we can't
+ mame_file *layoutfile;
+ file_error filerr = mame_fopen(SEARCHPATH_ARTWORK, fname, OPEN_FLAG_READ, &layoutfile);
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // read the file
+ rootnode = xml_file_read(mame_core_file(layoutfile), NULL);
+ mame_fclose(layoutfile);
+ }
+
+ // if we didn't get a properly-formatted XML file, record a warning and exit
+ if (rootnode == NULL)
+ {
+ if (filename[0] != '<')
+ mame_printf_warning("Improperly formatted XML file '%s', ignorning\n", filename);
+ else
+ mame_printf_warning("Improperly formatted XML string, ignorning");
+ return false;
+ }
+
+ // parse and catch any errors
+ bool result = true;
+ try
+ {
+ m_filelist.append(*auto_alloc(&m_manager.machine(), layout_file(m_manager.machine(), *rootnode, dirname)));
+ }
+ catch (emu_fatalerror &err)
+ {
+ if (filename[0] != '<')
+ mame_printf_warning("Error in XML file '%s': %s\n", filename, err.string());
+ else
+ mame_printf_warning("Error in XML string: %s", err.string());
+ result = false;
+ }
+
+ // free the root node
+ xml_file_free(rootnode);
+ return result;
+}
+
+
+//-------------------------------------------------
// add_container_primitives - add primitives
// based on the container
//-------------------------------------------------
@@ -1767,7 +1773,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
}
// add the overlay if it exists
- if (container.overlay() != NULL && screen_overlay_enabled())
+ if (container.overlay() != NULL && m_layerconfig.screen_overlay_enabled())
{
INT32 width, height;
@@ -1801,16 +1807,16 @@ void render_target::add_container_primitives(render_primitive_list &list, const
// for an element in the current state
//-------------------------------------------------
-void render_target::add_element_primitives(render_primitive_list &list, const object_transform &xform, const layout_element &element, int state, int blendmode)
+void render_target::add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode)
{
// if we're out of range, bail
- if (state > element.maxstate)
+ if (state > element.maxstate())
return;
if (state < 0)
state = 0;
// get a pointer to the relevant texture
- render_texture *texture = element.elemtex[state].texture;
+ render_texture *texture = element.state_texture(state);
if (texture != NULL)
{
render_primitive *prim = list.alloc(render_primitive::QUAD);
@@ -1856,11 +1862,13 @@ void render_target::add_element_primitives(render_primitive_list &list, const ob
// mapping points
//-------------------------------------------------
-bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, view_item *&mapped_item)
+bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask)
{
// default to point not mapped
mapped_x = -1.0;
mapped_y = -1.0;
+ mapped_input_tag = NULL;
+ mapped_input_mask = 0;
// convert target coordinates to float
float target_fx = (float)target_x / m_width;
@@ -1875,39 +1883,38 @@ bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_co
// this point was successfully mapped
mapped_x = target_fx;
mapped_y = target_fy;
- mapped_item = NULL;
return true;
}
return false;
}
// loop through each layer
- for (int layernum = 0; layernum < ITEM_LAYER_MAX; layernum++)
+ for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
{
int blendmode;
- int layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
- if (m_curview->layenabled[layer])
+ item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
+ if (m_curview->layer_enabled(layer))
{
// iterate over items in the layer
- for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
+ for (layout_view::item *item = m_curview->first_item(layer); item != NULL; item = item->next())
{
bool checkit;
// if we're looking for a particular container, verify that we have the right one
if (container != NULL)
- checkit = (item->element == NULL && container == m_manager.m_screen_container_list.find(item->index));
+ checkit = (item->screen() != NULL && &item->screen()->container() == container);
// otherwise, assume we're looking for an input
else
- checkit = (item->input_tag[0] != 0);
+ checkit = item->has_input();
// this target is worth looking at; now check the point
- if (checkit && target_fx >= item->bounds.x0 && target_fx < item->bounds.x1 && target_fy >= item->bounds.y0 && target_fy < item->bounds.y1)
+ if (checkit && target_fx >= item->bounds().x0 && target_fx < item->bounds().x1 && target_fy >= item->bounds().y0 && target_fy < item->bounds().y1)
{
// point successfully mapped
- mapped_x = (target_fx - item->bounds.x0) / (item->bounds.x1 - item->bounds.x0);
- mapped_y = (target_fy - item->bounds.y0) / (item->bounds.y1 - item->bounds.y0);
- mapped_item = item;
+ mapped_x = (target_fx - item->bounds().x0) / (item->bounds().x1 - item->bounds().x0);
+ mapped_y = (target_fy - item->bounds().y0) / (item->bounds().y1 - item->bounds().y0);
+ mapped_input_tag = item->input_tag_and_mask(mapped_input_mask);
return true;
}
}
@@ -1925,9 +1932,9 @@ bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_co
layout_view *render_target::view_by_index(int index) const
{
// scan the list of views within each layout, skipping those that don't apply
- for (layout_file *file = m_filelist; file != NULL; file = file->next)
- for (layout_view *view = file->viewlist; view != NULL; view = view->next)
- if (!(m_flags & RENDER_CREATE_NO_ART) || !layout_view_has_art(view))
+ for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
+ for (layout_view *view = file->first_view(); view != NULL; view = view->next())
+ if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
if (index-- == 0)
return view;
return NULL;
@@ -1945,9 +1952,9 @@ int render_target::view_index(layout_view &targetview) const
int index = 0;
// scan the list of views within each layout, skipping those that don't apply
- for (layout_file *file = m_filelist; file != NULL; file = file->next)
- for (layout_view *view = file->viewlist; view != NULL; view = view->next)
- if (!(m_flags & RENDER_CREATE_NO_ART) || !layout_view_has_art(view))
+ for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
+ for (layout_view *view = file->first_view(); view != NULL; view = view->next())
+ if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
{
if (&targetview == view)
return index;
@@ -2038,17 +2045,17 @@ bool render_target::config_save(xml_data_node &targetnode)
// output the view
if (m_curview != m_base_view)
{
- xml_set_attribute(&targetnode, "view", m_curview->name);
+ xml_set_attribute(&targetnode, "view", m_curview->name());
changed = true;
}
// output the layer config
if (m_layerconfig != m_base_layerconfig)
{
- xml_set_attribute_int(&targetnode, "backdrops", backdrops_enabled());
- xml_set_attribute_int(&targetnode, "overlays", overlays_enabled());
- xml_set_attribute_int(&targetnode, "bezels", bezels_enabled());
- xml_set_attribute_int(&targetnode, "zoom", zoom_to_screen());
+ xml_set_attribute_int(&targetnode, "backdrops", m_layerconfig.backdrops_enabled());
+ xml_set_attribute_int(&targetnode, "overlays", m_layerconfig.overlays_enabled());
+ xml_set_attribute_int(&targetnode, "bezels", m_layerconfig.bezels_enabled());
+ xml_set_attribute_int(&targetnode, "zoom", m_layerconfig.zoom_to_screen());
changed = true;
}
@@ -2360,7 +2367,7 @@ render_manager::render_manager(running_machine &machine)
// create one container per screen
for (screen_device *screen = screen_first(machine); screen != NULL; screen = screen_next(screen))
- container_alloc(screen);
+ screen->set_container(*container_alloc(screen));
}
@@ -2385,15 +2392,11 @@ render_manager::~render_manager()
bool render_manager::is_live(screen_device &screen) const
{
- int screen_index = screen.machine->m_devicelist.index(SCREEN, screen.tag());
- assert(screen_index != -1);
-
// iterate over all live targets and or together their screen masks
- UINT32 bitmask = 0;
for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
- bitmask |= target->view_screens(target->view());
-
- return (bitmask & (1 << screen_index)) ? true : false;
+ if (target->view_screens(target->view()).contains(screen))
+ return true;
+ return false;
}
@@ -2485,21 +2488,6 @@ float render_manager::ui_aspect()
//-------------------------------------------------
-// container_for_screen - return the container
-// allocated for the given screen device
-//-------------------------------------------------
-
-render_container *render_manager::container_for_screen(screen_device *screen)
-{
- // scan the list of screen containers for a match
- for (render_container *container = m_screen_container_list.first(); container != NULL; container = container->next())
- if (container->screen() == screen)
- return container;
- return NULL;
-}
-
-
-//-------------------------------------------------
// texture_alloc - allocate a new texture
//-------------------------------------------------
diff --git a/src/emu/render.h b/src/emu/render.h
index 599927de73b..b615da4309d 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -113,19 +113,6 @@ const UINT8 RENDER_CREATE_SINGLE_FILE = 0x02; // only load views from the file
const UINT8 RENDER_CREATE_HIDDEN = 0x04; // don't make this target visible
-// layer config masks
-const UINT8 LAYER_CONFIG_ENABLE_BACKDROP = 0x01; // enable backdrop layers
-const UINT8 LAYER_CONFIG_ENABLE_OVERLAY = 0x02; // enable overlay layers
-const UINT8 LAYER_CONFIG_ENABLE_BEZEL = 0x04; // enable bezel layers
-const UINT8 LAYER_CONFIG_ZOOM_TO_SCREEN = 0x08; // zoom to screen area by default
-const UINT8 LAYER_CONFIG_ENABLE_SCREEN_OVERLAY = 0x10; // enable screen overlays
-
-const UINT8 LAYER_CONFIG_DEFAULT = (LAYER_CONFIG_ENABLE_BACKDROP |
- LAYER_CONFIG_ENABLE_OVERLAY |
- LAYER_CONFIG_ENABLE_BEZEL |
- LAYER_CONFIG_ENABLE_SCREEN_OVERLAY);
-
-
// flags for primitives
const int PRIMFLAG_TEXORIENT_SHIFT = 0;
const UINT32 PRIMFLAG_TEXORIENT_MASK = 15 << PRIMFLAG_TEXORIENT_SHIFT;
@@ -183,10 +170,9 @@ class render_manager;
typedef struct _xml_data_node xml_data_node;
typedef struct _render_font render_font;
struct object_transform;
-typedef struct _layout_element layout_element;
-typedef struct _layout_view layout_view;
-typedef struct _view_item view_item;
-typedef struct _layout_file layout_file;
+class layout_element;
+class layout_view;
+class layout_file;
// texture scaling callback
@@ -243,6 +229,90 @@ struct render_texinfo
};
+// ======================> render_screen_list
+
+// a render_screen_list is a list of screen_devices
+class render_screen_list
+{
+ // screen list item
+ class item
+ {
+ friend class simple_list<item>;
+ friend class render_screen_list;
+
+ public:
+ // construction/destruction
+ item(screen_device &screen)
+ : m_next(NULL),
+ m_screen(screen) { }
+
+ // state
+ item * m_next; // next screen in list
+ screen_device & m_screen; // reference to screen device
+ };
+
+public:
+ // construction/destruction
+ render_screen_list(resource_pool &pool = global_resource_pool)
+ : m_list(pool) { }
+
+ // getters
+ int count() const { return m_list.count(); }
+
+ // operations
+ void add(screen_device &screen) { m_list.append(*pool_alloc(m_list.pool(), item(screen))); }
+ void reset() { m_list.reset(); }
+
+ // query
+ bool contains(screen_device &screen) const
+ {
+ for (item *curitem = m_list.first(); curitem != NULL; curitem = curitem->m_next)
+ if (&curitem->m_screen == &screen) return true;
+ return false;
+ }
+
+private:
+ // internal state
+ simple_list<item> m_list;
+};
+
+
+// ======================> render_layer_config
+
+// render_layer_config - describes the state of layers
+class render_layer_config
+{
+ static const UINT8 ENABLE_BACKDROP = 0x01; // enable backdrop layers
+ static const UINT8 ENABLE_OVERLAY = 0x02; // enable overlay layers
+ static const UINT8 ENABLE_BEZEL = 0x04; // enable bezel layers
+ static const UINT8 ZOOM_TO_SCREEN = 0x08; // zoom to screen area by default
+ static const UINT8 ENABLE_SCREEN_OVERLAY = 0x10; // enable screen overlays
+ static const UINT8 DEFAULT = ENABLE_BACKDROP | ENABLE_OVERLAY | ENABLE_BEZEL | ENABLE_SCREEN_OVERLAY;
+
+public:
+ render_layer_config()
+ : m_state(DEFAULT) { }
+
+ bool operator==(const render_layer_config &rhs) const { return m_state == rhs.m_state; }
+ bool operator!=(const render_layer_config &rhs) const { return m_state != rhs.m_state; }
+
+ bool backdrops_enabled() const { return ((m_state & ENABLE_BACKDROP) != 0); }
+ bool overlays_enabled() const { return ((m_state & ENABLE_OVERLAY) != 0); }
+ bool bezels_enabled() const { return ((m_state & ENABLE_BEZEL) != 0); }
+ bool screen_overlay_enabled() const { return ((m_state & ENABLE_SCREEN_OVERLAY) != 0); }
+ bool zoom_to_screen() const { return ((m_state & ZOOM_TO_SCREEN) != 0); }
+
+ render_layer_config &set_backdrops_enabled(bool enable) { if (enable) m_state |= ENABLE_BACKDROP; else m_state &= ~ENABLE_BACKDROP; return *this; }
+ render_layer_config &set_overlays_enabled(bool enable) { if (enable) m_state |= ENABLE_OVERLAY; else m_state &= ~ENABLE_OVERLAY; return *this; }
+ render_layer_config &set_bezels_enabled(bool enable) { if (enable) m_state |= ENABLE_BEZEL; else m_state &= ~ENABLE_BEZEL; return *this; }
+ render_layer_config &set_screen_overlay_enabled(bool enable) { if (enable) m_state |= ENABLE_SCREEN_OVERLAY; else m_state &= ~ENABLE_SCREEN_OVERLAY; return *this; }
+ render_layer_config &set_zoom_to_screen(bool zoom) { if (zoom) m_state |= ZOOM_TO_SCREEN; else m_state &= ~ZOOM_TO_SCREEN; return *this; }
+
+private:
+ UINT8 m_state;
+};
+
+
// ======================> render_primitive
// render_primitive - a single low-level primitive for the rendering engine
@@ -530,14 +600,9 @@ public:
float pixel_aspect() const { return m_pixel_aspect; }
float max_update_rate() const { return m_max_refresh; }
int orientation() const { return m_orientation; }
- int layer_config() const { return m_layerconfig; }
+ render_layer_config layer_config() const { return m_layerconfig; }
int view() const { return view_index(*m_curview); }
bool hidden() const { return ((m_flags & RENDER_CREATE_HIDDEN) != 0); }
- bool backdrops_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_BACKDROP) != 0; }
- bool overlays_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_OVERLAY) != 0; }
- bool bezels_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_BEZEL) != 0; }
- bool screen_overlay_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_SCREEN_OVERLAY) != 0; }
- bool zoom_to_screen() const { return (m_layerconfig & LAYER_CONFIG_ZOOM_TO_SCREEN) != 0; }
bool is_ui_target() const;
int index() const;
@@ -545,18 +610,26 @@ public:
void set_bounds(INT32 width, INT32 height, float pixel_aspect = 0);
void set_max_update_rate(float updates_per_second) { m_max_refresh = updates_per_second; }
void set_orientation(int orientation) { m_orientation = orientation; }
- void set_layer_config(int layerconfig);
void set_view(int viewindex);
void set_max_texture_size(int maxwidth, int maxheight);
- void set_backdrops_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_BACKDROP) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_BACKDROP)); }
- void set_overlays_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_OVERLAY) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_OVERLAY)); }
- void set_bezels_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_BEZEL) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_BEZEL)); }
- void set_screen_overlay_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_SCREEN_OVERLAY) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_SCREEN_OVERLAY)); }
- void set_zoom_to_screen(bool zoom) { set_layer_config(zoom ? (m_layerconfig | LAYER_CONFIG_ZOOM_TO_SCREEN) : (m_layerconfig & ~LAYER_CONFIG_ZOOM_TO_SCREEN)); }
+
+ // layer config getters
+ bool backdrops_enabled() const { return m_layerconfig.backdrops_enabled(); }
+ bool overlays_enabled() const { return m_layerconfig.overlays_enabled(); }
+ bool bezels_enabled() const { return m_layerconfig.bezels_enabled(); }
+ bool screen_overlay_enabled() const { return m_layerconfig.screen_overlay_enabled(); }
+ bool zoom_to_screen() const { return m_layerconfig.zoom_to_screen(); }
+
+ // layer config setters
+ void set_backdrops_enabled(bool enable) { m_layerconfig.set_backdrops_enabled(enable); update_layer_config(); }
+ void set_overlays_enabled(bool enable) { m_layerconfig.set_overlays_enabled(enable); update_layer_config(); }
+ void set_bezels_enabled(bool enable) { m_layerconfig.set_bezels_enabled(enable); update_layer_config(); }
+ void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); }
+ void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); }
// view information
const char *view_name(int viewindex);
- UINT32 view_screens(int viewindex);
+ const render_screen_list &view_screens(int viewindex);
// bounds computations
void compute_visible_area(INT32 target_width, INT32 target_height, float target_pixel_aspect, int target_orientation, INT32 &visible_width, INT32 &visible_height);
@@ -579,10 +652,12 @@ public:
private:
// internal helpers
+ void update_layer_config();
void load_layout_files(const char *layoutfile, bool singlefile);
+ bool load_layout_file(const char *dirname, const char *filename);
void add_container_primitives(render_primitive_list &list, const object_transform &xform, render_container &container, int blendmode);
- void add_element_primitives(render_primitive_list &list, const object_transform &xform, const layout_element &element, int state, int blendmode);
- bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, view_item *&mapped_item);
+ void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
+ bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask);
// config callbacks
void config_load(xml_data_node &targetnode);
@@ -606,7 +681,7 @@ private:
render_target * m_next; // link to next target
render_manager & m_manager; // reference to our owning manager
layout_view * m_curview; // current view
- layout_file * m_filelist; // list of layout files
+ simple_list<layout_file> &m_filelist; // list of layout files
UINT32 m_flags; // creation flags
render_primitive_list m_primlist[NUM_PRIMLISTS]; // list of primitives
int m_listindex; // index of next primlist to use
@@ -616,15 +691,17 @@ private:
float m_pixel_aspect; // aspect ratio of individual pixels
float m_max_refresh; // maximum refresh rate, 0 or if none
int m_orientation; // orientation
- int m_layerconfig; // layer configuration
+ render_layer_config m_layerconfig; // layer configuration
layout_view * m_base_view; // the view at the time of first frame
int m_base_orientation; // the orientation at the time of first frame
- int m_base_layerconfig; // the layer configuration at the time of first frame
+ render_layer_config m_base_layerconfig; // the layer configuration at the time of first frame
int m_maxtexwidth; // maximum width of a texture
int m_maxtexheight; // maximum height of a texture
simple_list<render_container> m_debug_containers; // list of debug containers
INT32 m_clear_extent_count; // number of clear extents
INT32 m_clear_extents[MAX_CLEAR_EXTENTS]; // array of clear extents
+
+ static const render_screen_list s_empty_screen_list;
};
@@ -658,9 +735,6 @@ public:
void set_ui_target(render_target &target) { m_ui_target = &target; }
float ui_aspect();
- // screen containers
- render_container *container_for_screen(screen_device *screen);
-
// UI containers
render_container &ui_container() const { assert(m_ui_container != NULL); return *m_ui_container; }
diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c
index 023e144732c..1886f44ab20 100644
--- a/src/emu/rendlay.c
+++ b/src/emu/rendlay.c
@@ -4,19 +4,38 @@
Core rendering layout parser and manager.
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
****************************************************************************
- Notes:
-
- Unlike the old system, the artwork is not rotated with the game
- orientation. This is to support odd configurations like two
- monitors in different orientations. You can specify an orientation
- for a backdrop/screen/overlay/bezel element, but it only applies
- to the artwork itself, and does not affect coordinates in any way.
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+****************************************************************************
Overview of objects:
@@ -72,19 +91,19 @@
STANDARD LAYOUTS
***************************************************************************/
-/* single screen layouts */
+// single screen layouts
#include "horizont.lh"
#include "vertical.lh"
-/* dual screen layouts */
+// dual screen layouts
#include "dualhsxs.lh"
#include "dualhovu.lh"
#include "dualhuov.lh"
-/* triple screen layouts */
+// triple screen layouts
#include "triphsxs.lh"
-/* generic color overlay layouts */
+// generic color overlay layouts
#include "ho20ffff.lh"
#include "ho2eff2e.lh"
#include "ho4f893d.lh"
@@ -96,94 +115,39 @@
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define LAYOUT_VERSION 2
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-#define LINE_CAP_NONE 0
-#define LINE_CAP_START 1
-#define LINE_CAP_END 2
+const int LAYOUT_VERSION = 2;
enum
{
- COMPONENT_TYPE_IMAGE = 0,
- COMPONENT_TYPE_RECT,
- COMPONENT_TYPE_DISK,
- COMPONENT_TYPE_TEXT,
- COMPONENT_TYPE_LED7SEG,
- COMPONENT_TYPE_LED14SEG,
- COMPONENT_TYPE_LED16SEG,
- COMPONENT_TYPE_LED14SEGSC,
- COMPONENT_TYPE_LED16SEGSC,
- COMPONENT_TYPE_DOTMATRIX,
- COMPONENT_TYPE_MAX
-};
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* an element_component represents an image, rectangle, or disk in an element */
-struct _element_component
-{
- element_component * next; /* link to next component */
- int type; /* type of component */
- int state; /* state where this component is visible (-1 means all states) */
- render_bounds bounds; /* bounds of the element */
- render_color color; /* color of the element */
- const char * string; /* string for text components */
- bitmap_t * bitmap; /* source bitmap for images */
- const char * dirname; /* directory name of image file (for lazy loading) */
- const char * imagefile; /* name of the image file (for lazy loading) */
- const char * alphafile; /* name of the alpha file (for lazy loading) */
- int hasalpha; /* is there any alpha component present? */
+ LINE_CAP_NONE = 0,
+ LINE_CAP_START = 1,
+ LINE_CAP_END = 2
};
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
-/* layout elements */
-static void layout_element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
-static void layout_element_draw_rect(bitmap_t &dest, const rectangle &bounds, const render_color &color);
-static void layout_element_draw_disk(bitmap_t &dest, const rectangle &bounds, const render_color &color);
-static void layout_element_draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds, const render_color &color, const char *string);
-static void layout_element_draw_led7seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-static void layout_element_draw_led14seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-static void layout_element_draw_led16seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-static void layout_element_draw_led14segsc(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-static void layout_element_draw_led16segsc(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-static void layout_element_draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, const render_color &color, int state);
-
-/* layout file parsing */
-static layout_element *load_layout_element(running_machine &machine, xml_data_node *elemnode, const char *dirname);
-static element_component *load_element_component(running_machine &machine, xml_data_node *compnode, const char *dirname);
-static layout_view *load_layout_view(running_machine &machine, xml_data_node *viewnode, layout_element *elemlist);
-static view_item *load_view_item(running_machine &machine, xml_data_node *itemnode, layout_element *elemlist);
-static bitmap_t *load_component_bitmap(const char *dirname, const char *file, const char *alphafile, int *hasalpha);
-static int load_bounds(running_machine &machine, xml_data_node *boundsnode, render_bounds *bounds);
-static int load_color(running_machine &machine, xml_data_node *colornode, render_color *color);
-static int load_orientation(running_machine &machine, xml_data_node *orientnode, int *orientation);
-static void layout_view_free(layout_view *view);
-static void layout_element_free(layout_element *element);
+const render_screen_list render_target::s_empty_screen_list;
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
-/*-------------------------------------------------
- gcd - compute the greatest common divisor (GCD)
- of two integers using the Euclidean algorithm
--------------------------------------------------*/
+//-------------------------------------------------
+// gcd - compute the greatest common divisor (GCD)
+// of two integers using the Euclidean algorithm
+//-------------------------------------------------
-INLINE int gcd(int a, int b)
+inline int gcd(int a, int b)
{
while (b != 0)
{
@@ -195,258 +159,594 @@ INLINE int gcd(int a, int b)
}
-/*-------------------------------------------------
- reduce_fraction - reduce a fraction by
- dividing out common factors
--------------------------------------------------*/
+//-------------------------------------------------
+// reduce_fraction - reduce a fraction by
+// dividing out common factors
+//-------------------------------------------------
-INLINE void reduce_fraction(int *num, int *den)
+inline void reduce_fraction(int &num, int &den)
{
- int div;
-
- /* search the greatest common divisor */
- div = gcd(*num, *den);
+ // search the greatest common divisor
+ int div = gcd(num, den);
- /* reduce the fraction if a common divisor has been found */
+ // reduce the fraction if a common divisor has been found
if (div > 1)
{
- *num /= div;
- *den /= div;
+ num /= div;
+ den /= div;
}
}
-/*-------------------------------------------------
- copy_string - make a copy of a string
--------------------------------------------------*/
-INLINE const char *copy_string(const char *string)
+//**************************************************************************
+// SHARED PARSING HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_variable_value - compute the value of
+// a variable in an XML attribute
+//-------------------------------------------------
+
+static int get_variable_value(running_machine &machine, const char *string, char **outputptr)
{
- char *newstring = global_alloc_array(char, strlen(string) + 1);
- strcpy(newstring, string);
- return newstring;
+ char temp[100];
+
+ // screen 0 parameters
+ for (const screen_device_config *devconfig = screen_first(machine.m_config); devconfig != NULL; devconfig = screen_next(devconfig))
+ {
+ int scrnum = machine.m_config.m_devicelist.index(SCREEN, devconfig->tag());
+
+ // native X aspect factor
+ sprintf(temp, "~scr%dnativexaspect~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ int num = devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x;
+ int den = devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y;
+ reduce_fraction(num, den);
+ *outputptr += sprintf(*outputptr, "%d", num);
+ return strlen(temp);
+ }
+
+ // native Y aspect factor
+ sprintf(temp, "~scr%dnativeyaspect~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ int num = devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x;
+ int den = devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y;
+ reduce_fraction(num, den);
+ *outputptr += sprintf(*outputptr, "%d", den);
+ return strlen(temp);
+ }
+
+ // native width
+ sprintf(temp, "~scr%dwidth~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ *outputptr += sprintf(*outputptr, "%d", devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x);
+ return strlen(temp);
+ }
+
+ // native height
+ sprintf(temp, "~scr%dheight~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ *outputptr += sprintf(*outputptr, "%d", devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y);
+ return strlen(temp);
+ }
+ }
+
+ // default: copy the first character and continue
+ **outputptr = *string;
+ *outputptr += 1;
+ return 1;
}
+//-------------------------------------------------
+// xml_get_attribute_string_with_subst - analog
+// to xml_get_attribute_string but with variable
+// substitution
+//-------------------------------------------------
-/***************************************************************************
- LAYOUT VIEWS
-***************************************************************************/
+static const char *xml_get_attribute_string_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, const char *defvalue)
+{
+ const char *str = xml_get_attribute_string(&node, attribute, NULL);
+ static char buffer[1000];
+
+ // if nothing, just return the default
+ if (str == NULL)
+ return defvalue;
+
+ // if no tildes, don't worry
+ if (strchr(str, '~') == NULL)
+ return str;
+
+ // make a copy of the string, doing substitutions along the way
+ const char *s;
+ char *d;
+ for (s = str, d = buffer; *s != 0; )
+ {
+ // if not a variable, just copy
+ if (*s != '~')
+ *d++ = *s++;
+
+ // extract the variable
+ else
+ s += get_variable_value(machine, s, &d);
+ }
+ *d = 0;
+ return buffer;
+}
-/*-------------------------------------------------
- layout_view_recompute - recompute the bounds
- and aspect ratio of a view and all of its
- contained items
--------------------------------------------------*/
-void layout_view_recompute(layout_view *view, int layerconfig)
+//-------------------------------------------------
+// xml_get_attribute_int_with_subst - analog
+// to xml_get_attribute_int but with variable
+// substitution
+//-------------------------------------------------
+
+static int xml_get_attribute_int_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, int defvalue)
{
- render_bounds target_bounds;
- float xscale, yscale;
- float xoffs, yoffs;
- int scrfirst = TRUE;
- int first = TRUE;
- int layer;
-
- /* reset the bounds */
- view->bounds.x0 = view->bounds.y0 = view->bounds.x1 = view->bounds.y1 = 0.0f;
- view->scrbounds.x0 = view->scrbounds.y0 = view->scrbounds.x1 = view->scrbounds.y1 = 0.0f;
- view->screens = 0;
-
- /* loop over all layers */
- for (layer = 0; layer < ITEM_LAYER_MAX; layer++)
+ const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
+ int value;
+
+ if (string == NULL)
+ return defvalue;
+ if (string[0] == '$')
+ return (sscanf(&string[1], "%X", &value) == 1) ? value : defvalue;
+ if (string[0] == '0' && string[1] == 'x')
+ return (sscanf(&string[2], "%X", &value) == 1) ? value : defvalue;
+ if (string[0] == '#')
+ return (sscanf(&string[1], "%d", &value) == 1) ? value : defvalue;
+ return (sscanf(&string[0], "%d", &value) == 1) ? value : defvalue;
+}
+
+
+//-------------------------------------------------
+// xml_get_attribute_float_with_subst - analog
+// to xml_get_attribute_float but with variable
+// substitution
+//-------------------------------------------------
+
+static float xml_get_attribute_float_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, float defvalue)
+{
+ const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
+ float value;
+
+ if (string == NULL || sscanf(string, "%f", &value) != 1)
+ return defvalue;
+ return value;
+}
+
+
+//-------------------------------------------------
+// parse_bounds - parse a bounds XML node
+//-------------------------------------------------
+
+void parse_bounds(running_machine &machine, xml_data_node *boundsnode, render_bounds &bounds)
+{
+ // skip if nothing
+ if (boundsnode == NULL)
{
- static const int layer_mask[ITEM_LAYER_MAX] = { LAYER_CONFIG_ENABLE_BACKDROP, 0, LAYER_CONFIG_ENABLE_OVERLAY, LAYER_CONFIG_ENABLE_BEZEL };
+ bounds.x0 = bounds.y0 = 0.0f;
+ bounds.x1 = bounds.y1 = 1.0f;
+ return;
+ }
- /* determine if this layer should be visible */
- view->layenabled[layer] = (layer_mask[layer] == 0 || (layerconfig & layer_mask[layer]));
+ // parse out the data
+ if (xml_get_attribute(boundsnode, "left") != NULL)
+ {
+ // left/right/top/bottom format
+ bounds.x0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "left", 0.0f);
+ bounds.x1 = xml_get_attribute_float_with_subst(machine, *boundsnode, "right", 1.0f);
+ bounds.y0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "top", 0.0f);
+ bounds.y1 = xml_get_attribute_float_with_subst(machine, *boundsnode, "bottom", 1.0f);
+ }
+ else if (xml_get_attribute(boundsnode, "x") != NULL)
+ {
+ // x/y/width/height format
+ bounds.x0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "x", 0.0f);
+ bounds.x1 = bounds.x0 + xml_get_attribute_float_with_subst(machine, *boundsnode, "width", 1.0f);
+ bounds.y0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "y", 0.0f);
+ bounds.y1 = bounds.y0 + xml_get_attribute_float_with_subst(machine, *boundsnode, "height", 1.0f);
+ }
+ else
+ throw emu_fatalerror("Illegal bounds value in XML");
- /* only do it if requested */
- if (view->layenabled[layer])
- {
- view_item *item;
+ // check for errors
+ if (bounds.x0 > bounds.x1 || bounds.y0 > bounds.y1)
+ throw emu_fatalerror("Illegal bounds value in XML: (%f-%f)-(%f-%f)", bounds.x0, bounds.x1, bounds.y0, bounds.y1);
+}
- for (item = view->itemlist[layer]; item != NULL; item = item->next)
- {
- /* accumulate bounds */
- if (first)
- view->bounds = item->rawbounds;
- else
- union_render_bounds(&view->bounds, &item->rawbounds);
- first = FALSE;
- /* accumulate screen bounds */
- if (item->element == NULL)
- {
- if (scrfirst)
- view->scrbounds = item->rawbounds;
- else
- union_render_bounds(&view->scrbounds, &item->rawbounds);
- scrfirst = FALSE;
+//-------------------------------------------------
+// parse_color - parse a color XML node
+//-------------------------------------------------
- /* accumulate the screens in use while we're scanning */
- view->screens |= 1 << item->index;
- }
- }
- }
+void parse_color(running_machine &machine, xml_data_node *colornode, render_color &color)
+{
+ // skip if nothing
+ if (colornode == NULL)
+ {
+ color.r = color.g = color.b = color.a = 1.0f;
+ return;
}
- /* if we have an explicit bounds, override it */
- if (view->expbounds.x1 > view->expbounds.x0)
- view->bounds = view->expbounds;
+ // parse out the data
+ color.r = xml_get_attribute_float_with_subst(machine, *colornode, "red", 1.0);
+ color.g = xml_get_attribute_float_with_subst(machine, *colornode, "green", 1.0);
+ color.b = xml_get_attribute_float_with_subst(machine, *colornode, "blue", 1.0);
+ color.a = xml_get_attribute_float_with_subst(machine, *colornode, "alpha", 1.0);
+
+ // check for errors
+ if (color.r < 0.0 || color.r > 1.0 || color.g < 0.0 || color.g > 1.0 ||
+ color.b < 0.0 || color.b > 1.0 || color.a < 0.0 || color.a > 1.0)
+ throw emu_fatalerror("Illegal ARGB color value in XML: %f,%f,%f,%f", color.r, color.g, color.b, color.a);
+}
+
- /* compute the aspect ratio of the view */
- view->aspect = (view->bounds.x1 - view->bounds.x0) / (view->bounds.y1 - view->bounds.y0);
- view->scraspect = (view->scrbounds.x1 - view->scrbounds.x0) / (view->scrbounds.y1 - view->scrbounds.y0);
+//-------------------------------------------------
+// parse_orientation - parse an orientation XML
+// node
+//-------------------------------------------------
- /* if we're handling things normally, the target bounds are (0,0)-(1,1) */
- if (!(layerconfig & LAYER_CONFIG_ZOOM_TO_SCREEN) || view->screens == 0)
+static void parse_orientation(running_machine &machine, xml_data_node *orientnode, int &orientation)
+{
+ // skip if nothing
+ if (orientnode == NULL)
{
- target_bounds.x0 = target_bounds.y0 = 0.0f;
- target_bounds.x1 = target_bounds.y1 = 1.0f;
+ orientation = ROT0;
+ return;
}
- /* if we're cropping, we want the screen area to fill (0,0)-(1,1) */
- else
+ // parse out the data
+ int rotate = xml_get_attribute_int_with_subst(machine, *orientnode, "rotate", 0);
+ switch (rotate)
{
- float targwidth = (view->bounds.x1 - view->bounds.x0) / (view->scrbounds.x1 - view->scrbounds.x0);
- float targheight = (view->bounds.y1 - view->bounds.y0) / (view->scrbounds.y1 - view->scrbounds.y0);
- target_bounds.x0 = (view->bounds.x0 - view->scrbounds.x0) / (view->bounds.x1 - view->bounds.x0) * targwidth;
- target_bounds.y0 = (view->bounds.y0 - view->scrbounds.y0) / (view->bounds.y1 - view->bounds.y0) * targheight;
- target_bounds.x1 = target_bounds.x0 + targwidth;
- target_bounds.y1 = target_bounds.y0 + targheight;
+ case 0: orientation = ROT0; break;
+ case 90: orientation = ROT90; break;
+ case 180: orientation = ROT180; break;
+ case 270: orientation = ROT270; break;
+ default: throw emu_fatalerror("Invalid rotation in XML orientation node: %d", rotate); break;
}
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "swapxy", "no")) == 0)
+ orientation ^= ORIENTATION_SWAP_XY;
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "flipx", "no")) == 0)
+ orientation ^= ORIENTATION_FLIP_X;
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "flipy", "no")) == 0)
+ orientation ^= ORIENTATION_FLIP_Y;
+}
+
+
- /* determine the scale/offset for normalization */
- xoffs = view->bounds.x0;
- yoffs = view->bounds.y0;
- xscale = (target_bounds.x1 - target_bounds.x0) / (view->bounds.x1 - view->bounds.x0);
- yscale = (target_bounds.y1 - target_bounds.y0) / (view->bounds.y1 - view->bounds.y0);
+//**************************************************************************
+// LAYOUT ELEMENT
+//**************************************************************************
- /* normalize all the item bounds */
- for (layer = 0; layer < ITEM_LAYER_MAX; layer++)
+//-------------------------------------------------
+// layout_element - constructor
+//-------------------------------------------------
+
+layout_element::layout_element(running_machine &machine, xml_data_node &elemnode, const char *dirname)
+ : m_next(NULL),
+ m_machine(machine),
+ m_complist(machine.m_respool),
+ m_defstate(0),
+ m_maxstate(0),
+ m_elemtex(NULL)
+{
+ // extract the name
+ const char *name = xml_get_attribute_string_with_subst(machine, elemnode, "name", NULL);
+ if (name == NULL)
+ throw emu_fatalerror("All layout elements must have a name!\n");
+ m_name = name;
+
+ // get the default state
+ m_defstate = xml_get_attribute_int_with_subst(machine, elemnode, "defstate", -1);
+
+ // parse components in order
+ bool first = true;
+ render_bounds bounds = { 0 };
+ for (xml_data_node *compnode = elemnode.child; compnode != NULL; compnode = compnode->next)
{
- view_item *item;
+ // allocate a new component
+ component &newcomp = m_complist.append(*auto_alloc(&machine, component(machine, *compnode, dirname)));
- /* adjust the bounds for each item */
- for (item = view->itemlist[layer]; item; item = item->next)
- {
- item->bounds.x0 = target_bounds.x0 + (item->rawbounds.x0 - xoffs) * xscale;
- item->bounds.x1 = target_bounds.x0 + (item->rawbounds.x1 - xoffs) * xscale;
- item->bounds.y0 = target_bounds.y0 + (item->rawbounds.y0 - yoffs) * yscale;
- item->bounds.y1 = target_bounds.y0 + (item->rawbounds.y1 - yoffs) * yscale;
- }
+ // accumulate bounds
+ if (first)
+ bounds = newcomp.m_bounds;
+ else
+ union_render_bounds(&bounds, &newcomp.m_bounds);
+ first = false;
+
+ // determine the maximum state
+ if (newcomp.m_state > m_maxstate)
+ m_maxstate = newcomp.m_state;
+ if (newcomp.m_type == component::CTYPE_LED7SEG)
+ m_maxstate = 255;
+ if (newcomp.m_type == component::CTYPE_LED14SEG)
+ m_maxstate = 16383;
+ if (newcomp.m_type == component::CTYPE_LED14SEGSC || newcomp.m_type == component::CTYPE_LED16SEG)
+ m_maxstate = 65535;
+ if (newcomp.m_type == component::CTYPE_LED16SEGSC)
+ m_maxstate = 262143;
+ if (newcomp.m_type == component::CTYPE_DOTMATRIX)
+ m_maxstate = 255;
}
+
+ // determine the scale/offset for normalization
+ float xoffs = bounds.x0;
+ float yoffs = bounds.y0;
+ float xscale = 1.0f / (bounds.x1 - bounds.x0);
+ float yscale = 1.0f / (bounds.y1 - bounds.y0);
+
+ // normalize all the component bounds
+ for (component *curcomp = m_complist.first(); curcomp != NULL; curcomp = curcomp->next())
+ {
+ curcomp->m_bounds.x0 = (curcomp->m_bounds.x0 - xoffs) * xscale;
+ curcomp->m_bounds.x1 = (curcomp->m_bounds.x1 - xoffs) * xscale;
+ curcomp->m_bounds.y0 = (curcomp->m_bounds.y0 - yoffs) * yscale;
+ curcomp->m_bounds.y1 = (curcomp->m_bounds.y1 - yoffs) * yscale;
+ }
+
+ // allocate an array of element textures for the states
+ m_elemtex = auto_alloc_array(&machine, texture, m_maxstate + 1);
}
+//-------------------------------------------------
+// ~layout_element - destructor
+//-------------------------------------------------
+
+layout_element::~layout_element()
+{
+ // loop over all states and free their textures
+ auto_free(&m_machine, m_elemtex);
+}
-/***************************************************************************
- LAYOUT ELEMENTS
-***************************************************************************/
-/*-------------------------------------------------
- layout_element_scale - scale an element by
- rendering all the components at the
- appropriate resolution
--------------------------------------------------*/
+//-------------------------------------------------
+// state_texture - return a pointer to a
+// render_texture for the given state, allocating
+// one if needed
+//-------------------------------------------------
-static void layout_element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+render_texture *layout_element::state_texture(int state)
{
- element_texture *elemtex = (element_texture *)param;
- element_component *component;
+ assert(state <= m_maxstate);
+ if (m_elemtex[state].m_texture == NULL)
+ {
+ m_elemtex[state].m_element = this;
+ m_elemtex[state].m_state = state;
+ m_elemtex[state].m_texture = m_machine.render().texture_alloc(element_scale, &m_elemtex[state]);
+ }
+ return m_elemtex[state].m_texture;
+}
+
+
+//-------------------------------------------------
+// element_scale - scale an element by rendering
+// all the components at the appropriate
+// resolution
+//-------------------------------------------------
- /* iterate over components that are part of the current state */
- for (component = elemtex->element->complist; component != NULL; component = component->next)
- if (component->state == -1 || component->state == elemtex->state)
+void layout_element::element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+{
+ texture *elemtex = (texture *)param;
+
+ // iterate over components that are part of the current state
+ for (component *curcomp = elemtex->m_element->m_complist.first(); curcomp != NULL; curcomp = curcomp->next())
+ if (curcomp->m_state == -1 || curcomp->m_state == elemtex->m_state)
{
+ // get the local scaled bounds
rectangle bounds;
+ bounds.min_x = render_round_nearest(curcomp->bounds().x0 * dest.width);
+ bounds.min_y = render_round_nearest(curcomp->bounds().y0 * dest.height);
+ bounds.max_x = render_round_nearest(curcomp->bounds().x1 * dest.width);
+ bounds.max_y = render_round_nearest(curcomp->bounds().y1 * dest.height);
- /* get the local scaled bounds */
- bounds.min_x = render_round_nearest(component->bounds.x0 * dest.width);
- bounds.min_y = render_round_nearest(component->bounds.y0 * dest.height);
- bounds.max_x = render_round_nearest(component->bounds.x1 * dest.width);
- bounds.max_y = render_round_nearest(component->bounds.y1 * dest.height);
-
- /* based on the component type, add to the texture */
- switch (component->type)
- {
- case COMPONENT_TYPE_IMAGE:
- if (component->bitmap == NULL)
- component->bitmap = load_component_bitmap(component->dirname, component->imagefile, component->alphafile, &component->hasalpha);
- render_resample_argb_bitmap_hq(
- BITMAP_ADDR32(&dest, bounds.min_y, bounds.min_x),
- dest.rowpixels,
- bounds.max_x - bounds.min_x,
- bounds.max_y - bounds.min_y,
- component->bitmap, NULL, &component->color);
- break;
-
- case COMPONENT_TYPE_RECT:
- layout_element_draw_rect(dest, bounds, component->color);
- break;
-
- case COMPONENT_TYPE_DISK:
- layout_element_draw_disk(dest, bounds, component->color);
- break;
-
- case COMPONENT_TYPE_TEXT:
- layout_element_draw_text(*elemtex->element->machine, dest, bounds, component->color, component->string);
- break;
-
- case COMPONENT_TYPE_LED7SEG:
- layout_element_draw_led7seg(dest, bounds, component->color, elemtex->state);
- break;
-
- case COMPONENT_TYPE_LED14SEG:
- layout_element_draw_led14seg(dest, bounds, component->color, elemtex->state);
- break;
-
- case COMPONENT_TYPE_LED16SEG:
- layout_element_draw_led16seg(dest, bounds, component->color, elemtex->state);
- break;
-
- case COMPONENT_TYPE_LED14SEGSC:
- layout_element_draw_led14segsc(dest, bounds, component->color, elemtex->state);
- break;
-
- case COMPONENT_TYPE_LED16SEGSC:
- layout_element_draw_led16segsc(dest, bounds, component->color, elemtex->state);
- break;
-
- case COMPONENT_TYPE_DOTMATRIX:
- layout_element_draw_dotmatrix(dest, bounds, component->color, elemtex->state);
- break;
- }
+ // based on the component type, add to the texture
+ curcomp->draw(elemtex->m_element->m_machine, dest, bounds, elemtex->m_state);
}
}
-/*-------------------------------------------------
- layout_element_draw_rect - draw a rectangle
- in the specified color
--------------------------------------------------*/
+//**************************************************************************
+// LAYOUT ELEMENT TEXTURE
+//**************************************************************************
+
+//-------------------------------------------------
+// texture - constructor
+//-------------------------------------------------
+
+layout_element::texture::texture()
+ : m_element(NULL),
+ m_texture(NULL),
+ m_state(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~texture - destructor
+//-------------------------------------------------
+
+layout_element::texture::~texture()
+{
+ if (m_element != NULL)
+ m_element->m_machine.render().texture_free(m_texture);
+}
+
+
+
+//**************************************************************************
+// LAYOUT ELEMENT COMPONENT
+//**************************************************************************
+
+//-------------------------------------------------
+// component - constructor
+//-------------------------------------------------
+
+layout_element::component::component(running_machine &machine, xml_data_node &compnode, const char *dirname)
+ : m_next(NULL),
+ m_type(CTYPE_INVALID),
+ m_state(0),
+ m_bitmap(NULL),
+ m_hasalpha(false)
+{
+ // fetch common data
+ m_state = xml_get_attribute_int_with_subst(machine, compnode, "state", -1);
+ parse_bounds(machine, xml_get_sibling(compnode.child, "bounds"), m_bounds);
+ parse_color(machine, xml_get_sibling(compnode.child, "color"), m_color);
+
+ // image nodes
+ if (strcmp(compnode.name, "image") == 0)
+ {
+ m_type = CTYPE_IMAGE;
+ m_dirname = dirname;
+ m_imagefile = xml_get_attribute_string_with_subst(machine, compnode, "file", "");
+ m_alphafile = xml_get_attribute_string_with_subst(machine, compnode, "alphafile", "");
+ }
+
+ // text nodes
+ else if (strcmp(compnode.name, "text") == 0)
+ {
+ m_type = CTYPE_TEXT;
+ m_string = xml_get_attribute_string_with_subst(machine, compnode, "string", "");
+ }
+
+ // dotmatrix nodes
+ else if (strcmp(compnode.name, "dotmatrix") == 0)
+ m_type = CTYPE_DOTMATRIX;
+
+ // led7seg nodes
+ else if (strcmp(compnode.name, "led7seg") == 0)
+ m_type = CTYPE_LED7SEG;
+
+ // led14seg nodes
+ else if (strcmp(compnode.name, "led14seg") == 0)
+ m_type = CTYPE_LED14SEG;
+
+ // led14segsc nodes
+ else if (strcmp(compnode.name, "led14segsc") == 0)
+ m_type = CTYPE_LED14SEGSC;
+
+ // led16seg nodes
+ else if (strcmp(compnode.name, "led16seg") == 0)
+ m_type = CTYPE_LED16SEG;
+
+ // led16segsc nodes
+ else if (strcmp(compnode.name, "led16segsc") == 0)
+ m_type = CTYPE_LED16SEGSC;
+
+ // rect nodes
+ else if (strcmp(compnode.name, "rect") == 0)
+ m_type = CTYPE_RECT;
+
+ // disk nodes
+ else if (strcmp(compnode.name, "disk") == 0)
+ m_type = CTYPE_DISK;
+
+ // error otherwise
+ else
+ throw emu_fatalerror("Unknown element component: %s", compnode.name);
+}
+
+
+//-------------------------------------------------
+// ~component - destructor
+//-------------------------------------------------
+
+layout_element::component::~component()
+{
+ global_free(m_bitmap);
+}
+
+
+//-------------------------------------------------
+// draw - draw a component
+//-------------------------------------------------
+
+void layout_element::component::draw(running_machine &machine, bitmap_t &dest, const rectangle &bounds, int state)
+{
+ switch (m_type)
+ {
+ case CTYPE_IMAGE:
+ if (m_bitmap == NULL)
+ m_bitmap = load_bitmap();
+ render_resample_argb_bitmap_hq(
+ BITMAP_ADDR32(&dest, bounds.min_y, bounds.min_x),
+ dest.rowpixels,
+ bounds.max_x - bounds.min_x,
+ bounds.max_y - bounds.min_y,
+ m_bitmap, NULL, &m_color);
+ break;
+
+ case CTYPE_RECT:
+ draw_rect(dest, bounds);
+ break;
+
+ case CTYPE_DISK:
+ draw_disk(dest, bounds);
+ break;
+
+ case CTYPE_TEXT:
+ draw_text(machine, dest, bounds);
+ break;
+
+ case CTYPE_LED7SEG:
+ draw_led7seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED14SEG:
+ draw_led14seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED16SEG:
+ draw_led16seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED14SEGSC:
+ draw_led14segsc(dest, bounds, state);
+ break;
+
+ case CTYPE_LED16SEGSC:
+ draw_led16segsc(dest, bounds, state);
+ break;
+
+ case CTYPE_DOTMATRIX:
+ draw_dotmatrix(dest, bounds, state);
+ break;
+
+ default:
+ throw emu_fatalerror("Unknown component type requested draw()");
+ }
+}
+
+
+//-------------------------------------------------
+// draw_rect - draw a rectangle in the specified
+// color
+//-------------------------------------------------
-static void layout_element_draw_rect(bitmap_t &dest, const rectangle &bounds, const render_color &color)
+void layout_element::component::draw_rect(bitmap_t &dest, const rectangle &bounds)
{
- UINT32 r, g, b, inva;
- UINT32 x, y;
-
- /* compute premultiplied colors */
- r = color.r * color.a * 255.0;
- g = color.g * color.a * 255.0;
- b = color.b * color.a * 255.0;
- inva = (1.0f - color.a) * 255.0;
-
- /* iterate over X and Y */
- for (y = bounds.min_y; y < bounds.max_y; y++)
- for (x = bounds.min_x; x < bounds.max_x; x++)
+ // compute premultiplied colors
+ UINT32 r = m_color.r * m_color.a * 255.0;
+ UINT32 g = m_color.g * m_color.a * 255.0;
+ UINT32 b = m_color.b * m_color.a * 255.0;
+ UINT32 inva = (1.0f - m_color.a) * 255.0;
+
+ // iterate over X and Y
+ for (UINT32 y = bounds.min_y; y < bounds.max_y; y++)
+ for (UINT32 x = bounds.min_x; x < bounds.max_x; x++)
{
UINT32 finalr = r;
UINT32 finalg = g;
UINT32 finalb = b;
- /* if we're translucent, add in the destination pixel contribution */
+ // if we're translucent, add in the destination pixel contribution
if (inva > 0)
{
UINT32 dpix = *BITMAP_ADDR32(&dest, y, x);
@@ -455,56 +755,50 @@ static void layout_element_draw_rect(bitmap_t &dest, const rectangle &bounds, co
finalb += (RGB_BLUE(dpix) * inva) >> 8;
}
- /* store the target pixel, dividing the RGBA values by the overall scale factor */
+ // store the target pixel, dividing the RGBA values by the overall scale factor
*BITMAP_ADDR32(&dest, y, x) = MAKE_ARGB(0xff, finalr, finalg, finalb);
}
}
-/*-------------------------------------------------
- layout_element_draw_disk - draw an ellipse
- in the specified color
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_disk - draw an ellipse in the specified
+// color
+//-------------------------------------------------
-static void layout_element_draw_disk(bitmap_t &dest, const rectangle &bounds, const render_color &color)
+void layout_element::component::draw_disk(bitmap_t &dest, const rectangle &bounds)
{
- float xcenter, ycenter;
- float xradius, yradius, ooyradius2;
- UINT32 r, g, b, inva;
- UINT32 x, y;
-
- /* compute premultiplied colors */
- r = color.r * color.a * 255.0;
- g = color.g * color.a * 255.0;
- b = color.b * color.a * 255.0;
- inva = (1.0f - color.a) * 255.0;
-
- /* find the center */
- xcenter = (float)(bounds.min_x + bounds.max_x) * 0.5f;
- ycenter = (float)(bounds.min_y + bounds.max_y) * 0.5f;
- xradius = (float)(bounds.max_x - bounds.min_x) * 0.5f;
- yradius = (float)(bounds.max_y - bounds.min_y) * 0.5f;
- ooyradius2 = 1.0f / (yradius * yradius);
-
- /* iterate over y */
- for (y = bounds.min_y; y < bounds.max_y; y++)
+ // compute premultiplied colors
+ UINT32 r = m_color.r * m_color.a * 255.0;
+ UINT32 g = m_color.g * m_color.a * 255.0;
+ UINT32 b = m_color.b * m_color.a * 255.0;
+ UINT32 inva = (1.0f - m_color.a) * 255.0;
+
+ // find the center
+ float xcenter = (float)(bounds.min_x + bounds.max_x) * 0.5f;
+ float ycenter = (float)(bounds.min_y + bounds.max_y) * 0.5f;
+ float xradius = (float)(bounds.max_x - bounds.min_x) * 0.5f;
+ float yradius = (float)(bounds.max_y - bounds.min_y) * 0.5f;
+ float ooyradius2 = 1.0f / (yradius * yradius);
+
+ // iterate over y
+ for (UINT32 y = bounds.min_y; y < bounds.max_y; y++)
{
float ycoord = ycenter - ((float)y + 0.5f);
float xval = xradius * sqrt(1.0f - (ycoord * ycoord) * ooyradius2);
- INT32 left, right;
- /* compute left/right coordinates */
- left = (INT32)(xcenter - xval + 0.5f);
- right = (INT32)(xcenter + xval + 0.5f);
+ // compute left/right coordinates
+ INT32 left = (INT32)(xcenter - xval + 0.5f);
+ INT32 right = (INT32)(xcenter + xval + 0.5f);
- /* draw this scanline */
- for (x = left; x < right; x++)
+ // draw this scanline
+ for (UINT32 x = left; x < right; x++)
{
UINT32 finalr = r;
UINT32 finalg = g;
UINT32 finalb = b;
- /* if we're translucent, add in the destination pixel contribution */
+ // if we're translucent, add in the destination pixel contribution
if (inva > 0)
{
UINT32 dpix = *BITMAP_ADDR32(&dest, y, x);
@@ -513,64 +807,57 @@ static void layout_element_draw_disk(bitmap_t &dest, const rectangle &bounds, co
finalb += (RGB_BLUE(dpix) * inva) >> 8;
}
- /* store the target pixel, dividing the RGBA values by the overall scale factor */
+ // store the target pixel, dividing the RGBA values by the overall scale factor
*BITMAP_ADDR32(&dest, y, x) = MAKE_ARGB(0xff, finalr, finalg, finalb);
}
}
}
-/*-------------------------------------------------
- layout_element_draw_text - draw text in the
- specified color
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_text - draw text in the specified color
+//-------------------------------------------------
-static void layout_element_draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds, const render_color &color, const char *string)
+void layout_element::component::draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds)
{
+ // compute premultiplied colors
+ UINT32 r = m_color.r * 255.0;
+ UINT32 g = m_color.g * 255.0;
+ UINT32 b = m_color.b * 255.0;
+ UINT32 a = m_color.a * 255.0;
+
+ // get the width of the string
render_font *font = render_font_alloc(machine, NULL);
- bitmap_t *tempbitmap;
- UINT32 r, g, b, a;
float aspect = 1.0f;
- INT32 curx, width;
- const char *s;
-
- /* compute premultiplied colors */
- r = color.r * 255.0;
- g = color.g * 255.0;
- b = color.b * 255.0;
- a = color.a * 255.0;
-
- /* get the width of the string */
+ INT32 width;
while (1)
{
- width = render_font_get_string_width(font, bounds.max_y - bounds.min_y, aspect, string);
+ width = render_font_get_string_width(font, bounds.max_y - bounds.min_y, aspect, m_string);
if (width < bounds.max_x - bounds.min_x)
break;
aspect *= 0.9f;
}
- curx = bounds.min_x + (bounds.max_x - bounds.min_x - width) / 2;
+ INT32 curx = bounds.min_x + (bounds.max_x - bounds.min_x - width) / 2;
- /* allocate a temporary bitmap */
- tempbitmap = global_alloc(bitmap_t(dest.width, dest.height, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(dest.width, dest.height, BITMAP_FORMAT_ARGB32));
- /* loop over characters */
- for (s = string; *s != 0; s++)
+ // loop over characters
+ for (const char *s = m_string; *s != 0; s++)
{
+ // get the font bitmap
rectangle chbounds;
- int x, y;
-
- /* get the font bitmap */
render_font_get_scaled_bitmap_and_bounds(font, tempbitmap, bounds.max_y - bounds.min_y, aspect, *s, &chbounds);
- /* copy the data into the target */
- for (y = 0; y < chbounds.max_y - chbounds.min_y; y++)
+ // copy the data into the target
+ for (int y = 0; y < chbounds.max_y - chbounds.min_y; y++)
{
int effy = bounds.min_y + y;
if (effy >= bounds.min_y && effy <= bounds.max_y)
{
UINT32 *src = BITMAP_ADDR32(tempbitmap, y, 0);
UINT32 *d = BITMAP_ADDR32(&dest, effy, 0);
- for (x = 0; x < chbounds.max_x - chbounds.min_x; x++)
+ for (int x = 0; x < chbounds.max_x - chbounds.min_x; x++)
{
int effx = curx + x + chbounds.min_x;
if (effx >= bounds.min_x && effx <= bounds.max_x)
@@ -579,12 +866,10 @@ static void layout_element_draw_text(running_machine &machine, bitmap_t &dest, c
if (spix != 0)
{
UINT32 dpix = d[effx];
- UINT32 ta, tr, tg, tb;
-
- ta = (a * (spix + 1)) >> 8;
- tr = (r * ta + RGB_RED(dpix) * (0x100 - ta)) >> 8;
- tg = (g * ta + RGB_GREEN(dpix) * (0x100 - ta)) >> 8;
- tb = (b * ta + RGB_BLUE(dpix) * (0x100 - ta)) >> 8;
+ UINT32 ta = (a * (spix + 1)) >> 8;
+ UINT32 tr = (r * ta + RGB_RED(dpix) * (0x100 - ta)) >> 8;
+ UINT32 tg = (g * ta + RGB_GREEN(dpix) * (0x100 - ta)) >> 8;
+ UINT32 tb = (b * ta + RGB_BLUE(dpix) * (0x100 - ta)) >> 8;
d[effx] = MAKE_ARGB(0xff, tr, tg, tb);
}
}
@@ -592,1575 +877,1080 @@ static void layout_element_draw_text(running_machine &machine, bitmap_t &dest, c
}
}
- /* advance in the X direction */
+ // advance in the X direction
curx += render_font_get_char_width(font, bounds.max_y - bounds.min_y, aspect, *s);
}
- /* free the temporary bitmap and font */
+ // free the temporary bitmap and font
global_free(tempbitmap);
render_font_free(font);
}
-/*-------------------------------------------------
- draw_segment_horizontal_caps - draw a
- horizontal LED segment with definable end
- and start points
--------------------------------------------------*/
+//-------------------------------------------------
+// load_bitmap - load a PNG file with artwork for
+// a component
+//-------------------------------------------------
-static void draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color)
+bitmap_t *layout_element::component::load_bitmap()
{
- int x, y;
+ // load the basic bitmap
+ bitmap_t *bitmap = render_load_png(OPTION_ARTPATH, m_dirname, m_imagefile, NULL, &m_hasalpha);
+ if (bitmap != NULL && m_alphafile)
- /* loop over the width of the segment */
- for (y = 0; y < width / 2; y++)
- {
- UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
- UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
- int ty = (y < width / 8) ? width / 8 : y;
-
- /* loop over the length of the segment */
- for (x = minx + ((caps & LINE_CAP_START) ? ty : 0); x < maxx - ((caps & LINE_CAP_END) ? ty : 0); x++)
- d0[x] = d1[x] = color;
- }
-}
-
-
-/*-------------------------------------------------
- draw_segment_horizontal - draw a horizontal
- LED segment
--------------------------------------------------*/
-
-static void draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color)
-{
- draw_segment_horizontal_caps(dest, minx, maxx, midy, width, LINE_CAP_START | LINE_CAP_END, color);
-}
-
-
-/*-------------------------------------------------
- draw_segment_vertical_caps - draw a
- vertical LED segment with definable end
- and start points
--------------------------------------------------*/
-
-static void draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color)
-{
- int x, y;
-
- /* loop over the width of the segment */
- for (x = 0; x < width / 2; x++)
- {
- UINT32 *d0 = BITMAP_ADDR32(&dest, 0, midx - x);
- UINT32 *d1 = BITMAP_ADDR32(&dest, 0, midx + x);
- int tx = (x < width / 8) ? width / 8 : x;
-
- /* loop over the length of the segment */
- for (y = miny + ((caps & LINE_CAP_START) ? tx : 0); y < maxy - ((caps & LINE_CAP_END) ? tx : 0); y++)
- d0[y * dest.rowpixels] = d1[y * dest.rowpixels] = color;
- }
-}
-
-
-/*-------------------------------------------------
- draw_segment_vertical - draw a vertical
- LED segment
--------------------------------------------------*/
-
-static void draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color)
-{
- draw_segment_vertical_caps(dest, miny, maxy, midx, width, LINE_CAP_START | LINE_CAP_END, color);
-}
-
-
-/*-------------------------------------------------
- draw_segment_diagonal_1 - draw a diagonal
- LED segment that looks like this: /
--------------------------------------------------*/
-
-static void draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
-{
- int x, y;
- float ratio;
-
- /* compute parameters */
- width *= 1.5;
- ratio = (maxy - miny - width) / (float)(maxx - minx);
-
- /* draw line */
- for (x = minx; x < maxx; x++)
- if (x >= 0 && x < dest.width)
- {
- UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
- int step = (x - minx) * ratio;
-
- for (y = maxy - width - step; y < maxy - step; y++)
- if (y >= 0 && y < dest.height)
- {
- d[y * dest.rowpixels] = color;
- }
- }
-}
-
-
-/*-------------------------------------------------
- draw_segment_diagonal_2 - draw a diagonal
- LED segment that looks like this: \
--------------------------------------------------*/
-
-static void draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
-{
- int x, y;
- float ratio;
-
- /* compute parameters */
- width *= 1.5;
- ratio = (maxy - miny - width) / (float)(maxx - minx);
-
- /* draw line */
- for (x = minx; x < maxx; x++)
- if (x >= 0 && x < dest.width)
+ // load the alpha bitmap if specified
+ if (render_load_png(OPTION_ARTPATH, m_dirname, m_alphafile, bitmap, &m_hasalpha) == NULL)
{
- UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
- int step = (x - minx) * ratio;
-
- for (y = miny + step; y < miny + step + width; y++)
- if (y >= 0 && y < dest.height)
- {
- d[y * dest.rowpixels] = color;
- }
+ global_free(bitmap);
+ bitmap = NULL;
}
-}
-
-
-/*-------------------------------------------------
- draw_segment_decimal - draw a decimal point
--------------------------------------------------*/
-
-static void draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color)
-{
- float ooradius2;
- UINT32 x, y;
-
- /* compute parameters */
- width /= 2;
- ooradius2 = 1.0f / (float)(width * width);
-
- /* iterate over y */
- for (y = 0; y <= width; y++)
- {
- UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
- UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
- float xval = width * sqrt(1.0f - (float)(y * y) * ooradius2);
- INT32 left, right;
- /* compute left/right coordinates */
- left = midx - (INT32)(xval + 0.5f);
- right = midx + (INT32)(xval + 0.5f);
-
- /* draw this scanline */
- for (x = left; x < right; x++)
- d0[x] = d1[x] = color;
- }
-}
-
-/*-------------------------------------------------
- draw_segment_comma - draw a comma tail
--------------------------------------------------*/
-#if 0
-static void draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
-{
- int x, y;
- float ratio;
-
- /* compute parameters */
- width *= 1.5;
- ratio = (maxy - miny - width) / (float)(maxx - minx);
-
- /* draw line */
- for (x = minx; x < maxx; x++)
+ // if we can't load the bitmap, allocate a dummy one and report an error
+ if (bitmap == NULL)
{
- UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
- int step = (x - minx) * ratio;
+ // draw some stripes in the bitmap
+ bitmap = global_alloc(bitmap_t(100, 100, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(bitmap, NULL, 0);
+ for (int step = 0; step < 100; step += 25)
+ for (int line = 0; line < 100; line++)
+ *BITMAP_ADDR32(bitmap, (step + line) % 100, line % 100) = MAKE_ARGB(0xff,0xff,0xff,0xff);
- for (y = maxy; y < maxy - width - step; y--)
- {
- d[y * dest.rowpixels] = color;
- }
+ // log an error
+ if (!m_alphafile)
+ mame_printf_warning("Unable to load component bitmap '%s'", m_imagefile.cstr());
+ else
+ mame_printf_warning("Unable to load component bitmap '%s'/'%s'", m_imagefile.cstr(), m_alphafile.cstr());
}
-}
-#endif
-
-
-/*-------------------------------------------------
- apply_skew - apply skew to a bitmap_t
--------------------------------------------------*/
-static void apply_skew(bitmap_t &dest, int skewwidth)
-{
- int x, y;
-
- for (y = 0; y < dest.height; y++)
- {
- UINT32 *destrow = BITMAP_ADDR32(&dest, y, 0);
- int offs = skewwidth * (dest.height - y) / dest.height;
- for (x = dest.width - skewwidth - 1; x >= 0; x--)
- destrow[x + offs] = destrow[x];
- for (x = 0; x < offs; x++)
- destrow[x] = 0;
- }
+ return bitmap;
}
-/*-------------------------------------------------
- layout_element_draw_led7seg - draw a
- 7-segment LCD
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_led7seg - draw a 7-segment LCD
+//-------------------------------------------------
-static void layout_element_draw_led7seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+void layout_element::component::draw_led7seg(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff,0xff,0xff,0xff);
const rgb_t offpen = MAKE_ARGB(0xff,0x20,0x20,0x20);
- int bmwidth, bmheight, segwidth, skewwidth;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 250;
- bmheight = 400;
- segwidth = 40;
- skewwidth = 40;
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
- /* allocate a temporary bitmap for drawing */
- tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff,0x00,0x00,0x00));
- /* top bar */
+ // top bar
draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 0)) ? onpen : offpen);
- /* top-right bar */
+ // top-right bar
draw_segment_vertical(*tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2, segwidth, (pattern & (1 << 1)) ? onpen : offpen);
- /* bottom-right bar */
+ // bottom-right bar
draw_segment_vertical(*tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2, segwidth, (pattern & (1 << 2)) ? onpen : offpen);
- /* bottom bar */
+ // bottom bar
draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2, segwidth, (pattern & (1 << 3)) ? onpen : offpen);
- /* bottom-left bar */
+ // bottom-left bar
draw_segment_vertical(*tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 4)) ? onpen : offpen);
- /* top-left bar */
+ // top-left bar
draw_segment_vertical(*tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 5)) ? onpen : offpen);
- /* middle bar */
+ // middle bar
draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight/2, segwidth, (pattern & (1 << 6)) ? onpen : offpen);
- /* apply skew */
+ // apply skew
apply_skew(*tempbitmap, 40);
- /* decimal point */
+ // decimal point
draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 7)) ? onpen : offpen);
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/*-------------------------------------------------
- layout_element_draw_led14seg - draw a
- 14-segment LCD
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_led14seg - draw a 14-segment LCD
+//-------------------------------------------------
-static void layout_element_draw_led14seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+void layout_element::component::draw_led14seg(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
- int bmwidth, bmheight, segwidth, skewwidth;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 250;
- bmheight = 400;
- segwidth = 40;
- skewwidth = 40;
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
- /* allocate a temporary bitmap for drawing */
- tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
- /* top bar */
+ // top bar
draw_segment_horizontal(*tempbitmap,
0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 0)) ? onpen : offpen);
- /* right-top bar */
+ // right-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 1)) ? onpen : offpen);
- /* right-bottom bar */
+ // right-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 2)) ? onpen : offpen);
- /* bottom bar */
+ // bottom bar
draw_segment_horizontal(*tempbitmap,
0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
segwidth, (pattern & (1 << 3)) ? onpen : offpen);
- /* left-bottom bar */
+ // left-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 4)) ? onpen : offpen);
- /* left-top bar */
+ // left-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 5)) ? onpen : offpen);
- /* horizontal-middle-left bar */
+ // horizontal-middle-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
segwidth, LINE_CAP_START, (pattern & (1 << 6)) ? onpen : offpen);
- /* horizontal-middle-right bar */
+ // horizontal-middle-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
segwidth, LINE_CAP_END, (pattern & (1 << 7)) ? onpen : offpen);
- /* vertical-middle-top bar */
+ // vertical-middle-top bar
draw_segment_vertical_caps(*tempbitmap,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 8)) ? onpen : offpen);
- /* vertical-middle-bottom bar */
+ // vertical-middle-bottom bar
draw_segment_vertical_caps(*tempbitmap,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 9)) ? onpen : offpen);
- /* diagonal-left-bottom bar */
+ // diagonal-left-bottom bar
draw_segment_diagonal_1(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 10)) ? onpen : offpen);
- /* diagonal-left-top bar */
+ // diagonal-left-top bar
draw_segment_diagonal_2(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 11)) ? onpen : offpen);
- /* diagonal-right-top bar */
+ // diagonal-right-top bar
draw_segment_diagonal_1(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 12)) ? onpen : offpen);
- /* diagonal-right-bottom bar */
+ // diagonal-right-bottom bar
draw_segment_diagonal_2(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 13)) ? onpen : offpen);
- /* apply skew */
+ // apply skew
apply_skew(*tempbitmap, 40);
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/*-------------------------------------------------
- layout_element_draw_led14segsc - draw a
- 14-segment LCD with semicolon (2 extra segments)
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_led14segsc - draw a 14-segment LCD with
+// semicolon (2 extra segments)
+//-------------------------------------------------
-static void layout_element_draw_led14segsc(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+void layout_element::component::draw_led14segsc(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
- int bmwidth, bmheight, segwidth, skewwidth;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 250;
- bmheight = 400;
- segwidth = 40;
- skewwidth = 40;
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
- /* allocate a temporary bitmap for drawing, adding some extra space for the tail */
- tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing, adding some extra space for the tail
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
- /* top bar */
+ // top bar
draw_segment_horizontal(*tempbitmap,
0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 0)) ? onpen : offpen);
- /* right-top bar */
+ // right-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 1)) ? onpen : offpen);
- /* right-bottom bar */
+ // right-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 2)) ? onpen : offpen);
- /* bottom bar */
+ // bottom bar
draw_segment_horizontal(*tempbitmap,
0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
segwidth, (pattern & (1 << 3)) ? onpen : offpen);
- /* left-bottom bar */
+ // left-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 4)) ? onpen : offpen);
- /* left-top bar */
+ // left-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 5)) ? onpen : offpen);
- /* horizontal-middle-left bar */
+ // horizontal-middle-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
segwidth, LINE_CAP_START, (pattern & (1 << 6)) ? onpen : offpen);
- /* horizontal-middle-right bar */
+ // horizontal-middle-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
segwidth, LINE_CAP_END, (pattern & (1 << 7)) ? onpen : offpen);
- /* vertical-middle-top bar */
+ // vertical-middle-top bar
draw_segment_vertical_caps(*tempbitmap,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 8)) ? onpen : offpen);
- /* vertical-middle-bottom bar */
+ // vertical-middle-bottom bar
draw_segment_vertical_caps(*tempbitmap,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 9)) ? onpen : offpen);
- /* diagonal-left-bottom bar */
+ // diagonal-left-bottom bar
draw_segment_diagonal_1(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 10)) ? onpen : offpen);
- /* diagonal-left-top bar */
+ // diagonal-left-top bar
draw_segment_diagonal_2(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 11)) ? onpen : offpen);
- /* diagonal-right-top bar */
+ // diagonal-right-top bar
draw_segment_diagonal_1(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 12)) ? onpen : offpen);
- /* diagonal-right-bottom bar */
+ // diagonal-right-bottom bar
draw_segment_diagonal_2(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 13)) ? onpen : offpen);
- /* apply skew */
+ // apply skew
apply_skew(*tempbitmap, 40);
- /* decimal point */
+ // decimal point
draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 14)) ? onpen : offpen);
- /* comma tail */
+ // comma tail
draw_segment_diagonal_1(*tempbitmap,
bmwidth - (segwidth/2), bmwidth + segwidth,
bmheight - (segwidth), bmheight + segwidth*1.5,
segwidth/2, (pattern & (1 << 15)) ? onpen : offpen);
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/*-------------------------------------------------
- layout_element_draw_led16seg - draw a
- 16-segment LCD
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_led16seg - draw a 16-segment LCD
+//-------------------------------------------------
-static void layout_element_draw_led16seg(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+void layout_element::component::draw_led16seg(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
- int bmwidth, bmheight, segwidth, skewwidth;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 250;
- bmheight = 400;
- segwidth = 40;
- skewwidth = 40;
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
- /* allocate a temporary bitmap for drawing */
- tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
- /* top-left bar */
+ // top-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
segwidth, LINE_CAP_START, (pattern & (1 << 0)) ? onpen : offpen);
- /* top-right bar */
+ // top-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
segwidth, LINE_CAP_END, (pattern & (1 << 1)) ? onpen : offpen);
- /* right-top bar */
+ // right-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 2)) ? onpen : offpen);
- /* right-bottom bar */
+ // right-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 3)) ? onpen : offpen);
- /* bottom-right bar */
+ // bottom-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
segwidth, LINE_CAP_END, (pattern & (1 << 4)) ? onpen : offpen);
- /* bottom-left bar */
+ // bottom-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
segwidth, LINE_CAP_START, (pattern & (1 << 5)) ? onpen : offpen);
- /* left-bottom bar */
+ // left-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 6)) ? onpen : offpen);
- /* left-top bar */
+ // left-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 7)) ? onpen : offpen);
- /* horizontal-middle-left bar */
+ // horizontal-middle-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
segwidth, LINE_CAP_START, (pattern & (1 << 8)) ? onpen : offpen);
- /* horizontal-middle-right bar */
+ // horizontal-middle-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
segwidth, LINE_CAP_END, (pattern & (1 << 9)) ? onpen : offpen);
- /* vertical-middle-top bar */
+ // vertical-middle-top bar
draw_segment_vertical_caps(*tempbitmap,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 10)) ? onpen : offpen);
- /* vertical-middle-bottom bar */
+ // vertical-middle-bottom bar
draw_segment_vertical_caps(*tempbitmap,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 11)) ? onpen : offpen);
- /* diagonal-left-bottom bar */
+ // diagonal-left-bottom bar
draw_segment_diagonal_1(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 12)) ? onpen : offpen);
- /* diagonal-left-top bar */
+ // diagonal-left-top bar
draw_segment_diagonal_2(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 13)) ? onpen : offpen);
- /* diagonal-right-top bar */
+ // diagonal-right-top bar
draw_segment_diagonal_1(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 14)) ? onpen : offpen);
- /* diagonal-right-bottom bar */
+ // diagonal-right-bottom bar
draw_segment_diagonal_2(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 15)) ? onpen : offpen);
- /* apply skew */
+ // apply skew
apply_skew(*tempbitmap, 40);
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/*-------------------------------------------------
- layout_element_draw_led16segsc - draw a
- 16-segment LCD with semicolon (2 extra segments)
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_led16segsc - draw a 16-segment LCD with
+// semicolon (2 extra segments)
+//-------------------------------------------------
-static void layout_element_draw_led16segsc(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+void layout_element::component::draw_led16segsc(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
- int bmwidth, bmheight, segwidth, skewwidth;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 250;
- bmheight = 400;
- segwidth = 40;
- skewwidth = 40;
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
- /* allocate a temporary bitmap for drawing */
- tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
- /* top-left bar */
+ // top-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
segwidth, LINE_CAP_START, (pattern & (1 << 0)) ? onpen : offpen);
- /* top-right bar */
+ // top-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
segwidth, LINE_CAP_END, (pattern & (1 << 1)) ? onpen : offpen);
- /* right-top bar */
+ // right-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 2)) ? onpen : offpen);
- /* right-bottom bar */
+ // right-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
segwidth, (pattern & (1 << 3)) ? onpen : offpen);
- /* bottom-right bar */
+ // bottom-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
segwidth, LINE_CAP_END, (pattern & (1 << 4)) ? onpen : offpen);
- /* bottom-left bar */
+ // bottom-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
segwidth, LINE_CAP_START, (pattern & (1 << 5)) ? onpen : offpen);
- /* left-bottom bar */
+ // left-bottom bar
draw_segment_vertical(*tempbitmap,
bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 6)) ? onpen : offpen);
- /* left-top bar */
+ // left-top bar
draw_segment_vertical(*tempbitmap,
0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
segwidth, (pattern & (1 << 7)) ? onpen : offpen);
- /* horizontal-middle-left bar */
+ // horizontal-middle-left bar
draw_segment_horizontal_caps(*tempbitmap,
0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
segwidth, LINE_CAP_START, (pattern & (1 << 8)) ? onpen : offpen);
- /* horizontal-middle-right bar */
+ // horizontal-middle-right bar
draw_segment_horizontal_caps(*tempbitmap,
0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
segwidth, LINE_CAP_END, (pattern & (1 << 9)) ? onpen : offpen);
- /* vertical-middle-top bar */
+ // vertical-middle-top bar
draw_segment_vertical_caps(*tempbitmap,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 10)) ? onpen : offpen);
- /* vertical-middle-bottom bar */
+ // vertical-middle-bottom bar
draw_segment_vertical_caps(*tempbitmap,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
segwidth, LINE_CAP_NONE, (pattern & (1 << 11)) ? onpen : offpen);
- /* diagonal-left-bottom bar */
+ // diagonal-left-bottom bar
draw_segment_diagonal_1(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 12)) ? onpen : offpen);
- /* diagonal-left-top bar */
+ // diagonal-left-top bar
draw_segment_diagonal_2(*tempbitmap,
0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 13)) ? onpen : offpen);
- /* diagonal-right-top bar */
+ // diagonal-right-top bar
draw_segment_diagonal_1(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
segwidth, (pattern & (1 << 14)) ? onpen : offpen);
- /* diagonal-right-bottom bar */
+ // diagonal-right-bottom bar
draw_segment_diagonal_2(*tempbitmap,
bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
segwidth, (pattern & (1 << 15)) ? onpen : offpen);
- /* decimal point */
+ // decimal point
draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 16)) ? onpen : offpen);
- /* comma tail */
+ // comma tail
draw_segment_diagonal_1(*tempbitmap,
bmwidth - (segwidth/2), bmwidth + segwidth,
bmheight - (segwidth), bmheight + segwidth*1.5,
segwidth/2, (pattern & (1 << 17)) ? onpen : offpen);
- /* apply skew */
+ // apply skew
apply_skew(*tempbitmap, 40);
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/*-------------------------------------------------
- layout_element_draw_dotmatrix - draw a
- row of 8 dots for a dotmatrix
--------------------------------------------------*/
-static void layout_element_draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, const render_color &color, int pattern)
+//-------------------------------------------------
+// draw_dotmatrix - draw a row of 8 dots for a
+// dotmatrix
+//-------------------------------------------------
+
+void layout_element::component::draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, int pattern)
{
const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
- int bmwidth, bmheight, dotwidth, i;
- bitmap_t *tempbitmap;
- /* sizes for computation */
- bmwidth = 2000;
- bmheight = 300;
- dotwidth = 250;
+ // sizes for computation
+ int bmwidth = 2000;
+ int bmheight = 300;
+ int dotwidth = 250;
- /* allocate a temporary bitmap for drawing */
- tempbitmap = global_alloc(bitmap_t(bmwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth, bmheight, BITMAP_FORMAT_ARGB32));
bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
- for (i = 0; i < 8; i++)
- {// height
+ for (int i = 0; i < 8; i++)
draw_segment_decimal(*tempbitmap, ((dotwidth/2 )+ (i * dotwidth)), bmheight/2, dotwidth, (pattern & (1 << i))?onpen:offpen);
- }
- /* resample to the target size */
- render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &color);
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
global_free(tempbitmap);
}
-/***************************************************************************
- LAYOUT FILE PARSING
-***************************************************************************/
-
-/*-------------------------------------------------
- get_variable_value - compute the value of
- a variable in an XML attribute
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_horizontal_caps - draw a
+// horizontal LED segment with definable end
+// and start points
+//-------------------------------------------------
-static int get_variable_value(running_machine &machine, const char *string, char **outputptr)
+void layout_element::component::draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color)
{
- const screen_device_config *devconfig;
- int num, den;
- char temp[100];
-
- /* screen 0 parameters */
- for (devconfig = screen_first(machine.m_config); devconfig != NULL; devconfig = screen_next(devconfig))
+ // loop over the width of the segment
+ for (int y = 0; y < width / 2; y++)
{
- int scrnum = machine.m_config.m_devicelist.index(SCREEN, devconfig->tag());
-
- /* native X aspect factor */
- sprintf(temp, "~scr%dnativexaspect~", scrnum);
- if (!strncmp(string, temp, strlen(temp)))
- {
- num = devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x;
- den = devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y;
- reduce_fraction(&num, &den);
- *outputptr += sprintf(*outputptr, "%d", num);
- return strlen(temp);
- }
-
- /* native Y aspect factor */
- sprintf(temp, "~scr%dnativeyaspect~", scrnum);
- if (!strncmp(string, temp, strlen(temp)))
- {
- num = devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x;
- den = devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y;
- reduce_fraction(&num, &den);
- *outputptr += sprintf(*outputptr, "%d", den);
- return strlen(temp);
- }
-
- /* native width */
- sprintf(temp, "~scr%dwidth~", scrnum);
- if (!strncmp(string, temp, strlen(temp)))
- {
- *outputptr += sprintf(*outputptr, "%d", devconfig->visible_area().max_x + 1 - devconfig->visible_area().min_x);
- return strlen(temp);
- }
+ UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
+ int ty = (y < width / 8) ? width / 8 : y;
- /* native height */
- sprintf(temp, "~scr%dheight~", scrnum);
- if (!strncmp(string, temp, strlen(temp)))
- {
- *outputptr += sprintf(*outputptr, "%d", devconfig->visible_area().max_y + 1 - devconfig->visible_area().min_y);
- return strlen(temp);
- }
+ // loop over the length of the segment
+ for (int x = minx + ((caps & LINE_CAP_START) ? ty : 0); x < maxx - ((caps & LINE_CAP_END) ? ty : 0); x++)
+ d0[x] = d1[x] = color;
}
-
- /* default: copy the first character and continue */
- **outputptr = *string;
- *outputptr += 1;
- return 1;
}
-/*-------------------------------------------------
- xml_get_attribute_string_with_subst - analog
- to xml_get_attribute_string but with variable
- substitution
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_horizontal - draw a horizontal
+// LED segment
+//-------------------------------------------------
-static const char *xml_get_attribute_string_with_subst(running_machine &machine, xml_data_node *node, const char *attribute, const char *defvalue)
+void layout_element::component::draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color)
{
- const char *str = xml_get_attribute_string(node, attribute, NULL);
- static char buffer[1000];
- const char *s;
- char *d;
+ draw_segment_horizontal_caps(dest, minx, maxx, midy, width, LINE_CAP_START | LINE_CAP_END, color);
+}
- /* if nothing, just return the default */
- if (str == NULL)
- return defvalue;
- /* if no tildes, don't worry */
- if (strchr(str, '~') == NULL)
- return str;
+//-------------------------------------------------
+// draw_segment_vertical_caps - draw a
+// vertical LED segment with definable end
+// and start points
+//-------------------------------------------------
- /* make a copy of the string, doing substitutions along the way */
- for (s = str, d = buffer; *s != 0; )
+void layout_element::component::draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color)
+{
+ // loop over the width of the segment
+ for (int x = 0; x < width / 2; x++)
{
- /* if not a variable, just copy */
- if (*s != '~')
- *d++ = *s++;
+ UINT32 *d0 = BITMAP_ADDR32(&dest, 0, midx - x);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, 0, midx + x);
+ int tx = (x < width / 8) ? width / 8 : x;
- /* extract the variable */
- else
- s += get_variable_value(machine, s, &d);
+ // loop over the length of the segment
+ for (int y = miny + ((caps & LINE_CAP_START) ? tx : 0); y < maxy - ((caps & LINE_CAP_END) ? tx : 0); y++)
+ d0[y * dest.rowpixels] = d1[y * dest.rowpixels] = color;
}
- *d = 0;
- return buffer;
}
-/*-------------------------------------------------
- xml_get_attribute_int_with_subst - analog
- to xml_get_attribute_int but with variable
- substitution
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_vertical - draw a vertical
+// LED segment
+//-------------------------------------------------
-static int xml_get_attribute_int_with_subst(running_machine &machine, xml_data_node *node, const char *attribute, int defvalue)
+void layout_element::component::draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color)
{
- const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
- int value;
-
- if (string == NULL)
- return defvalue;
- if (string[0] == '$')
- return (sscanf(&string[1], "%X", &value) == 1) ? value : defvalue;
- if (string[0] == '0' && string[1] == 'x')
- return (sscanf(&string[2], "%X", &value) == 1) ? value : defvalue;
- if (string[0] == '#')
- return (sscanf(&string[1], "%d", &value) == 1) ? value : defvalue;
- return (sscanf(&string[0], "%d", &value) == 1) ? value : defvalue;
+ draw_segment_vertical_caps(dest, miny, maxy, midx, width, LINE_CAP_START | LINE_CAP_END, color);
}
-/*-------------------------------------------------
- xml_get_attribute_float_with_subst - analog
- to xml_get_attribute_float but with variable
- substitution
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_diagonal_1 - draw a diagonal
+// LED segment that looks like this: /
+//-------------------------------------------------
-static float xml_get_attribute_float_with_subst(running_machine &machine, xml_data_node *node, const char *attribute, float defvalue)
+void layout_element::component::draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
{
- const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
- float value;
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
- if (!string || sscanf(string, "%f", &value) != 1)
- return defvalue;
- return value;
+ // draw line
+ for (int x = minx; x < maxx; x++)
+ if (x >= 0 && x < dest.width)
+ {
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
+
+ for (int y = maxy - width - step; y < maxy - step; y++)
+ if (y >= 0 && y < dest.height)
+ d[y * dest.rowpixels] = color;
+ }
}
-/*-------------------------------------------------
- layout_file_load - parse a layout XML file
- into a layout_file
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_diagonal_2 - draw a diagonal
+// LED segment that looks like this:
+//-------------------------------------------------
-layout_file *layout_file_load(running_machine &machine, const char *dirname, const char *filename)
+void layout_element::component::draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
{
- xml_data_node *rootnode, *mamelayoutnode, *elemnode, *viewnode;
- layout_element **elemnext;
- layout_view **viewnext;
- layout_file *file;
- int version;
-
- /* if the first character of the "file" is an open brace, assume it is an XML string */
- if (filename[0] == '<')
- rootnode = xml_string_read(filename, NULL);
-
- /* otherwise, assume it is a file */
- else
- {
- file_error filerr;
- mame_file *layoutfile;
-
- astring fname(filename, ".lay");
- if (dirname != NULL)
- fname.ins(0, PATH_SEPARATOR).ins(0, dirname);
-
- filerr = mame_fopen(SEARCHPATH_ARTWORK, fname, OPEN_FLAG_READ, &layoutfile);
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
- if (filerr != FILERR_NONE)
- return NULL;
- rootnode = xml_file_read(mame_core_file(layoutfile), NULL);
- mame_fclose(layoutfile);
- }
+ // draw line
+ for (int x = minx; x < maxx; x++)
+ if (x >= 0 && x < dest.width)
+ {
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
- /* if unable to parse the file, just bail */
- if (rootnode == NULL)
- return NULL;
+ for (int y = miny + step; y < miny + step + width; y++)
+ if (y >= 0 && y < dest.height)
+ d[y * dest.rowpixels] = color;
+ }
+}
- /* allocate the layout group object first */
- file = global_alloc_clear(layout_file);
- /* find the layout node */
- mamelayoutnode = xml_get_sibling(rootnode->child, "mamelayout");
- if (mamelayoutnode == NULL)
- fatalerror("Invalid XML file: missing mamelayout node");
+//-------------------------------------------------
+// draw_segment_decimal - draw a decimal point
+//-------------------------------------------------
- /* validate the config data version */
- version = xml_get_attribute_int(mamelayoutnode, "version", 0);
- if (version != LAYOUT_VERSION)
- fatalerror("Invalid XML file: unsupported version");
+void layout_element::component::draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color)
+{
+ // compute parameters
+ width /= 2;
+ float ooradius2 = 1.0f / (float)(width * width);
- /* parse all the elements */
- file->elemlist = NULL;
- elemnext = &file->elemlist;
- for (elemnode = xml_get_sibling(mamelayoutnode->child, "element"); elemnode; elemnode = xml_get_sibling(elemnode->next, "element"))
+ // iterate over y
+ for (UINT32 y = 0; y <= width; y++)
{
- layout_element *element = load_layout_element(machine, elemnode, dirname);
- if (element == NULL)
- goto error;
-
- /* add to the end of the list */
- *elemnext = element;
- elemnext = &element->next;
- }
+ UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
+ float xval = width * sqrt(1.0f - (float)(y * y) * ooradius2);
+ INT32 left, right;
- /* parse all the views */
- file->viewlist = NULL;
- viewnext = &file->viewlist;
- for (viewnode = xml_get_sibling(mamelayoutnode->child, "view"); viewnode; viewnode = xml_get_sibling(viewnode->next, "view"))
- {
- layout_view *view = load_layout_view(machine, viewnode, file->elemlist);
- if (view == NULL)
- goto error;
+ // compute left/right coordinates
+ left = midx - (INT32)(xval + 0.5f);
+ right = midx + (INT32)(xval + 0.5f);
- /* add to the end of the list */
- *viewnext = view;
- viewnext = &view->next;
+ // draw this scanline
+ for (UINT32 x = left; x < right; x++)
+ d0[x] = d1[x] = color;
}
-
- xml_file_free(rootnode);
- return file;
-
-error:
- layout_file_free(file);
- xml_file_free(rootnode);
- return NULL;
}
-/*-------------------------------------------------
- load_layout_element - parse an element XML
- node from the layout file
--------------------------------------------------*/
+//-------------------------------------------------
+// draw_segment_comma - draw a comma tail
+//-------------------------------------------------
-static layout_element *load_layout_element(running_machine &machine, xml_data_node *elemnode, const char *dirname)
+void layout_element::component::draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
{
- render_bounds bounds = { 0 };
- element_component **nextcomp;
- element_component *component;
- xml_data_node *compnode;
- layout_element *element;
- float xscale, yscale;
- float xoffs, yoffs;
- const char *name;
- int state;
- int first;
-
- /* allocate a new element */
- element = global_alloc_clear(layout_element);
-
- /* extract the name */
- name = xml_get_attribute_string_with_subst(machine, elemnode, "name", NULL);
- if (name == NULL)
- {
- logerror("All layout elements must have a name!\n");
- goto error;
- }
- element->machine = &machine;
- element->name = copy_string(name);
- element->defstate = xml_get_attribute_int_with_subst(machine, elemnode, "defstate", -1);
-
- /* parse components in order */
- first = TRUE;
- nextcomp = &element->complist;
- for (compnode = elemnode->child; compnode; compnode = compnode->next)
- {
- /* allocate a new component */
- element_component *new_component = load_element_component(machine, compnode, dirname);
- if (new_component == NULL)
- goto error;
-
- /* link it into the list */
- *nextcomp = new_component;
- nextcomp = &new_component->next;
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
- /* accumulate bounds */
- if (first)
- bounds = new_component->bounds;
- else
- union_render_bounds(&bounds, &new_component->bounds);
- first = FALSE;
-
- /* determine the maximum state */
- if (new_component->state > element->maxstate)
- element->maxstate = new_component->state;
- if (new_component->type == COMPONENT_TYPE_LED7SEG)
- element->maxstate = 255;
- if (new_component->type == COMPONENT_TYPE_LED14SEG)
- element->maxstate = 16383;
- if (new_component->type == COMPONENT_TYPE_LED14SEGSC || new_component->type == COMPONENT_TYPE_LED16SEG)
- element->maxstate = 65535;
- if (new_component->type == COMPONENT_TYPE_LED16SEGSC)
- element->maxstate = 262143;
- if (new_component->type == COMPONENT_TYPE_DOTMATRIX)
- element->maxstate = 255;
- }
- /* determine the scale/offset for normalization */
- xoffs = bounds.x0;
- yoffs = bounds.y0;
- xscale = 1.0f / (bounds.x1 - bounds.x0);
- yscale = 1.0f / (bounds.y1 - bounds.y0);
-
- /* normalize all the component bounds */
- for (component = element->complist; component != NULL; component = component->next)
+ // draw line
+ for (int x = minx; x < maxx; x++)
{
- component->bounds.x0 = (component->bounds.x0 - xoffs) * xscale;
- component->bounds.x1 = (component->bounds.x1 - xoffs) * xscale;
- component->bounds.y0 = (component->bounds.y0 - yoffs) * yscale;
- component->bounds.y1 = (component->bounds.y1 - yoffs) * yscale;
- }
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
- /* allocate an array of element textures for the states */
- element->elemtex = global_alloc_array(element_texture, element->maxstate + 1);
- for (state = 0; state <= element->maxstate; state++)
- {
- element->elemtex[state].element = element;
- element->elemtex[state].state = state;
- element->elemtex[state].texture = machine.render().texture_alloc(layout_element_scale, &element->elemtex[state]);
+ for (int y = maxy; y < maxy - width - step; y--)
+ d[y * dest.rowpixels] = color;
}
-
- return element;
-
-error:
- layout_element_free(element);
- return NULL;
}
-/*-------------------------------------------------
- load_element_component - parse a component
- XML node (image/rect/disk)
--------------------------------------------------*/
+//-------------------------------------------------
+// apply_skew - apply skew to a bitmap_t
+//-------------------------------------------------
-static element_component *load_element_component(running_machine &machine, xml_data_node *compnode, const char *dirname)
+void layout_element::component::apply_skew(bitmap_t &dest, int skewwidth)
{
- element_component *component;
-
- /* allocate memory for the component */
- component = global_alloc_clear(element_component);
-
- /* fetch common data */
- component->state = xml_get_attribute_int_with_subst(machine, compnode, "state", -1);
- if (load_bounds(machine, xml_get_sibling(compnode->child, "bounds"), &component->bounds))
- goto error;
- if (load_color(machine, xml_get_sibling(compnode->child, "color"), &component->color))
- goto error;
-
- /* image nodes */
- if (strcmp(compnode->name, "image") == 0)
- {
- const char *file = xml_get_attribute_string_with_subst(machine, compnode, "file", NULL);
- const char *afile = xml_get_attribute_string_with_subst(machine, compnode, "alphafile", NULL);
-
- /* load and allocate the bitmap */
- component->type = COMPONENT_TYPE_IMAGE;
- component->dirname = (dirname == NULL) ? NULL : copy_string(dirname);
- component->imagefile = (file == NULL) ? NULL : copy_string(file);
- component->alphafile = (afile == NULL) ? NULL : copy_string(afile);
- }
-
- /* text nodes */
- else if (strcmp(compnode->name, "text") == 0)
+ for (int y = 0; y < dest.height; y++)
{
- const char *text = xml_get_attribute_string_with_subst(machine, compnode, "string", "");
- char *string;
-
- /* allocate a copy of the string */
- component->type = COMPONENT_TYPE_TEXT;
- string = global_alloc_array(char, strlen(text) + 1);
- strcpy(string, text);
- component->string = string;
+ UINT32 *destrow = BITMAP_ADDR32(&dest, y, 0);
+ int offs = skewwidth * (dest.height - y) / dest.height;
+ for (int x = dest.width - skewwidth - 1; x >= 0; x--)
+ destrow[x + offs] = destrow[x];
+ for (int x = 0; x < offs; x++)
+ destrow[x] = 0;
}
+}
- /* dotmatrix nodes */
- else if (strcmp(compnode->name, "dotmatrix") == 0)
- component->type = COMPONENT_TYPE_DOTMATRIX;
- /* led7seg nodes */
- else if (strcmp(compnode->name, "led7seg") == 0)
- component->type = COMPONENT_TYPE_LED7SEG;
- /* led14seg nodes */
- else if (strcmp(compnode->name, "led14seg") == 0)
- component->type = COMPONENT_TYPE_LED14SEG;
+//**************************************************************************
+// LAYOUT VIEW
+//**************************************************************************
- /* led14segsc nodes */
- else if (strcmp(compnode->name, "led14segsc") == 0)
- component->type = COMPONENT_TYPE_LED14SEGSC;
+//-------------------------------------------------
+// layout_view - constructor
+//-------------------------------------------------
- /* led16seg nodes */
- else if (strcmp(compnode->name, "led16seg") == 0)
- component->type = COMPONENT_TYPE_LED16SEG;
+layout_view::layout_view(running_machine &machine, xml_data_node &viewnode, simple_list<layout_element> &elemlist)
+ : m_next(NULL),
+ m_aspect(1.0f),
+ m_scraspect(1.0f),
+ m_screens(machine.m_respool),
+ m_backdrop_list(machine.m_respool),
+ m_screen_list(machine.m_respool),
+ m_overlay_list(machine.m_respool),
+ m_bezel_list(machine.m_respool)
+{
+ // allocate a copy of the name
+ m_name = xml_get_attribute_string_with_subst(machine, viewnode, "name", "");
- /* led16segsc nodes */
- else if (strcmp(compnode->name, "led16segsc") == 0)
- component->type = COMPONENT_TYPE_LED16SEGSC;
+ // if we have a bounds item, load it
+ xml_data_node *boundsnode = xml_get_sibling(viewnode.child, "bounds");
+ m_expbounds.x0 = m_expbounds.y0 = m_expbounds.x1 = m_expbounds.y1 = 0;
+ if (boundsnode != NULL)
+ parse_bounds(machine, xml_get_sibling(boundsnode, "bounds"), m_expbounds);
- /* rect nodes */
- else if (strcmp(compnode->name, "rect") == 0)
- component->type = COMPONENT_TYPE_RECT;
+ // load backdrop items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "backdrop"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "backdrop"))
+ m_backdrop_list.append(*auto_alloc(&machine, item(machine, *itemnode, elemlist)));
- /* disk nodes */
- else if (strcmp(compnode->name, "disk") == 0)
- component->type = COMPONENT_TYPE_DISK;
+ // load screen items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "screen"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "screen"))
+ m_screen_list.append(*auto_alloc(&machine, item(machine, *itemnode, elemlist)));
- /* error otherwise */
- else
- fatalerror("Unknown element component: %s", compnode->name);
+ // load overlay items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "overlay"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "overlay"))
+ m_overlay_list.append(*auto_alloc(&machine, item(machine, *itemnode, elemlist)));
- return component;
+ // load bezel items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "bezel"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "bezel"))
+ m_bezel_list.append(*auto_alloc(&machine, item(machine, *itemnode, elemlist)));
-error:
- global_free(component);
- return NULL;
+ // recompute the data for the view based on a default layer config
+ recompute(render_layer_config());
}
-/*-------------------------------------------------
- load_layout_view - parse a view XML node
--------------------------------------------------*/
+//-------------------------------------------------
+// layout_view - destructor
+//-------------------------------------------------
-static layout_view *load_layout_view(running_machine &machine, xml_data_node *viewnode, layout_element *elemlist)
+layout_view::~layout_view()
{
- xml_data_node *boundsnode;
- view_item **itemnext;
- layout_view *view;
- int layer;
-
- /* first allocate memory */
- view = global_alloc_clear(layout_view);
+}
- /* allocate a copy of the name */
- view->name = copy_string(xml_get_attribute_string_with_subst(machine, viewnode, "name", ""));
- /* if we have a bounds item, load it */
- boundsnode = xml_get_sibling(viewnode->child, "bounds");
- if (boundsnode != NULL && load_bounds(machine, xml_get_sibling(boundsnode, "bounds"), &view->expbounds))
- goto error;
+//-------------------------------------------------
+// first_item - return the first item in the
+// appropriate list
+//-------------------------------------------------
- /* loop over all the layer types we support */
- for (layer = 0; layer < ITEM_LAYER_MAX; layer++)
+layout_view::item *layout_view::first_item(item_layer layer) const
+{
+ switch (layer)
{
- static const char *const layer_node_name[ITEM_LAYER_MAX] = { "backdrop", "screen", "overlay", "bezel" };
- xml_data_node *itemnode;
-
- /* initialize the list */
- view->itemlist[layer] = NULL;
- itemnext = &view->itemlist[layer];
-
- /* parse all of the elements of that type */
- for (itemnode = xml_get_sibling(viewnode->child, layer_node_name[layer]); itemnode; itemnode = xml_get_sibling(itemnode->next, layer_node_name[layer]))
- {
- view_item *item = load_view_item(machine, itemnode, elemlist);
- if (!item)
- goto error;
-
- /* add to the end of the list */
- *itemnext = item;
- itemnext = &item->next;
- }
+ case ITEM_LAYER_BACKDROP: return m_backdrop_list.first();
+ case ITEM_LAYER_SCREEN: return m_screen_list.first();
+ case ITEM_LAYER_OVERLAY: return m_overlay_list.first();
+ case ITEM_LAYER_BEZEL: return m_bezel_list.first();
+ default: return NULL;
}
-
- /* recompute the data for the view */
- layout_view_recompute(view, ~0);
- return view;
-
-error:
- layout_view_free(view);
- return NULL;
}
-/*-------------------------------------------------
- load_view_item - parse an item XML node
--------------------------------------------------*/
+//-------------------------------------------------
+// recompute - recompute the bounds and aspect
+// ratio of a view and all of its contained items
+//-------------------------------------------------
-static view_item *load_view_item(running_machine &machine, xml_data_node *itemnode, layout_element *elemlist)
+void layout_view::recompute(render_layer_config layerconfig)
{
- view_item *item;
- const char *name;
+ // reset the bounds
+ m_bounds.x0 = m_bounds.y0 = m_bounds.x1 = m_bounds.y1 = 0.0f;
+ m_scrbounds.x0 = m_scrbounds.y0 = m_scrbounds.x1 = m_scrbounds.y1 = 0.0f;
+ m_screens.reset();
+
+ // loop over all layers
+ bool first = true;
+ bool scrfirst = true;
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
+ {
+ // determine if this layer should be visible
+ switch (layer)
+ {
+ case ITEM_LAYER_BACKDROP: m_layenabled[layer] = layerconfig.backdrops_enabled(); break;
+ case ITEM_LAYER_OVERLAY: m_layenabled[layer] = layerconfig.overlays_enabled(); break;
+ case ITEM_LAYER_BEZEL: m_layenabled[layer] = layerconfig.bezels_enabled(); break;
+ default: m_layenabled[layer] = true; break;
+ }
- /* allocate a new item */
- item = global_alloc_clear(view_item);
+ // only do it if requested
+ if (m_layenabled[layer])
+ for (item *curitem = first_item(layer); curitem != NULL; curitem = curitem->next())
+ {
+ // accumulate bounds
+ if (first)
+ m_bounds = curitem->m_rawbounds;
+ else
+ union_render_bounds(&m_bounds, &curitem->m_rawbounds);
+ first = false;
- /* allocate a copy of the output name */
- item->output_name = copy_string(xml_get_attribute_string_with_subst(machine, itemnode, "name", ""));
+ // accumulate screen bounds
+ if (curitem->m_screen != NULL)
+ {
+ if (scrfirst)
+ m_scrbounds = curitem->m_rawbounds;
+ else
+ union_render_bounds(&m_scrbounds, &curitem->m_rawbounds);
+ scrfirst = false;
- /* allocate a copy of the input tag */
- item->input_tag = copy_string(xml_get_attribute_string_with_subst(machine, itemnode, "inputtag", ""));
+ // accumulate the screens in use while we're scanning
+ m_screens.add(*curitem->m_screen);
+ }
+ }
+ }
- /* find the associated element */
- name = xml_get_attribute_string_with_subst(machine, itemnode, "element", NULL);
- if (name != NULL)
- {
- layout_element *element;
+ // if we have an explicit bounds, override it
+ if (m_expbounds.x1 > m_expbounds.x0)
+ m_bounds = m_expbounds;
- /* search the list of elements for a match */
- for (element = elemlist; element; element = element->next)
- if (strcmp(name, element->name) == 0)
- break;
+ // compute the aspect ratio of the view
+ m_aspect = (m_bounds.x1 - m_bounds.x0) / (m_bounds.y1 - m_bounds.y0);
+ m_scraspect = (m_scrbounds.x1 - m_scrbounds.x0) / (m_scrbounds.y1 - m_scrbounds.y0);
- /* error if not found */
- if (element == NULL)
- fatalerror("Unable to find layout element %s", name);
- item->element = element;
- }
-
- /* fetch common data */
- item->index = xml_get_attribute_int_with_subst(machine, itemnode, "index", -1);
- item->input_mask = xml_get_attribute_int_with_subst(machine, itemnode, "inputmask", 0);
- if (item->output_name[0] != 0 && item->element != 0)
- output_set_value(item->output_name, item->element->defstate);
- if (load_bounds(machine, xml_get_sibling(itemnode->child, "bounds"), &item->rawbounds))
- goto error;
- if (load_color(machine, xml_get_sibling(itemnode->child, "color"), &item->color))
- goto error;
- if (load_orientation(machine, xml_get_sibling(itemnode->child, "orientation"), &item->orientation))
- goto error;
-
- /* sanity checks */
- if (strcmp(itemnode->name, "screen") == 0)
+ // if we're handling things normally, the target bounds are (0,0)-(1,1)
+ render_bounds target_bounds;
+ if (!layerconfig.zoom_to_screen() || m_screens.count() == 0)
{
- if (item->index < 0)
- fatalerror("Layout references invalid screen index %d", item->index);
+ target_bounds.x0 = target_bounds.y0 = 0.0f;
+ target_bounds.x1 = target_bounds.y1 = 1.0f;
}
+
+ // if we're cropping, we want the screen area to fill (0,0)-(1,1)
else
{
- if (item->element == NULL)
- fatalerror("Layout item of type %s require an element tag", itemnode->name);
+ float targwidth = (m_bounds.x1 - m_bounds.x0) / (m_scrbounds.x1 - m_scrbounds.x0);
+ float targheight = (m_bounds.y1 - m_bounds.y0) / (m_scrbounds.y1 - m_scrbounds.y0);
+ target_bounds.x0 = (m_bounds.x0 - m_scrbounds.x0) / (m_bounds.x1 - m_bounds.x0) * targwidth;
+ target_bounds.y0 = (m_bounds.y0 - m_scrbounds.y0) / (m_bounds.y1 - m_bounds.y0) * targheight;
+ target_bounds.x1 = target_bounds.x0 + targwidth;
+ target_bounds.y1 = target_bounds.y0 + targheight;
}
- return item;
-
-error:
- if (item->output_name != NULL)
- global_free(item->output_name);
- if (item->input_tag != NULL)
- global_free(item->input_tag);
- global_free(item);
- return NULL;
-}
+ // determine the scale/offset for normalization
+ float xoffs = m_bounds.x0;
+ float yoffs = m_bounds.y0;
+ float xscale = (target_bounds.x1 - target_bounds.x0) / (m_bounds.x1 - m_bounds.x0);
+ float yscale = (target_bounds.y1 - target_bounds.y0) / (m_bounds.y1 - m_bounds.y0);
-
-/*-------------------------------------------------
- load_component_bitmap - load a PNG file
- with artwork for a component
--------------------------------------------------*/
-
-static bitmap_t *load_component_bitmap(const char *dirname, const char *file, const char *alphafile, int *hasalpha)
-{
- bitmap_t *bitmap;
-
- /* load the basic bitmap */
- bitmap = render_load_png(OPTION_ARTPATH, dirname, file, NULL, hasalpha);
- if (bitmap != NULL && alphafile != NULL)
-
- /* load the alpha bitmap if specified */
- if (render_load_png(OPTION_ARTPATH, dirname, alphafile, bitmap, hasalpha) == NULL)
+ // normalize all the item bounds
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
+ for (item *curitem = first_item(layer); curitem != NULL; curitem = curitem->next())
{
- global_free(bitmap);
- bitmap = NULL;
+ curitem->m_bounds.x0 = target_bounds.x0 + (curitem->m_rawbounds.x0 - xoffs) * xscale;
+ curitem->m_bounds.x1 = target_bounds.x0 + (curitem->m_rawbounds.x1 - xoffs) * xscale;
+ curitem->m_bounds.y0 = target_bounds.y0 + (curitem->m_rawbounds.y0 - yoffs) * yscale;
+ curitem->m_bounds.y1 = target_bounds.y0 + (curitem->m_rawbounds.y1 - yoffs) * yscale;
}
+}
- /* if we can't load the bitmap, allocate a dummy one and report an error */
- if (bitmap == NULL)
- {
- int step, line;
- /* draw some stripes in the bitmap */
- bitmap = global_alloc(bitmap_t(100, 100, BITMAP_FORMAT_ARGB32));
- bitmap_fill(bitmap, NULL, 0);
- for (step = 0; step < 100; step += 25)
- for (line = 0; line < 100; line++)
- *BITMAP_ADDR32(bitmap, (step + line) % 100, line % 100) = MAKE_ARGB(0xff,0xff,0xff,0xff);
- /* log an error */
- if (alphafile == NULL)
- logerror("Unable to load component bitmap '%s'", file);
- else
- logerror("Unable to load component bitmap '%s'/'%s'", file, alphafile);
- }
+//**************************************************************************
+// LAYOUT VIEW ITEM
+//**************************************************************************
- return bitmap;
-}
+//-------------------------------------------------
+// item - constructor
+//-------------------------------------------------
+layout_view::item::item(running_machine &machine, xml_data_node &itemnode, simple_list<layout_element> &elemlist)
+ : m_next(NULL),
+ m_element(NULL),
+ m_input_mask(0),
+ m_screen(NULL),
+ m_orientation(ROT0)
+{
+ // allocate a copy of the output name
+ m_output_name = xml_get_attribute_string_with_subst(machine, itemnode, "name", "");
-/*-------------------------------------------------
- load_bounds - parse a bounds XML node
--------------------------------------------------*/
+ // allocate a copy of the input tag
+ m_input_tag = xml_get_attribute_string_with_subst(machine, itemnode, "inputtag", "");
-static int load_bounds(running_machine &machine, xml_data_node *boundsnode, render_bounds *bounds)
-{
- /* skip if nothing */
- if (boundsnode == NULL)
+ // find the associated element
+ const char *name = xml_get_attribute_string_with_subst(machine, itemnode, "element", NULL);
+ if (name != NULL)
{
- bounds->x0 = bounds->y0 = 0.0f;
- bounds->x1 = bounds->y1 = 1.0f;
- return 0;
- }
+ // search the list of elements for a match
+ for (m_element = elemlist.first(); m_element != NULL; m_element = m_element->next())
+ if (strcmp(name, m_element->name()) == 0)
+ break;
- /* parse out the data */
- if (xml_get_attribute(boundsnode, "left") != NULL)
- {
- /* left/right/top/bottom format */
- bounds->x0 = xml_get_attribute_float_with_subst(machine, boundsnode, "left", 0.0f);
- bounds->x1 = xml_get_attribute_float_with_subst(machine, boundsnode, "right", 1.0f);
- bounds->y0 = xml_get_attribute_float_with_subst(machine, boundsnode, "top", 0.0f);
- bounds->y1 = xml_get_attribute_float_with_subst(machine, boundsnode, "bottom", 1.0f);
+ // error if not found
+ if (m_element == NULL)
+ throw emu_fatalerror("Unable to find layout element %s", name);
}
- else if (xml_get_attribute(boundsnode, "x") != NULL)
+
+ // fetch common data
+ int index = xml_get_attribute_int_with_subst(machine, itemnode, "index", -1);
+ if (index != -1)
+ m_screen = downcast<screen_device *>(machine.m_devicelist.find(SCREEN, index));
+ m_input_mask = xml_get_attribute_int_with_subst(machine, itemnode, "inputmask", 0);
+ if (m_output_name[0] != 0 && m_element != NULL)
+ output_set_value(m_output_name, m_element->default_state());
+ parse_bounds(machine, xml_get_sibling(itemnode.child, "bounds"), m_rawbounds);
+ parse_color(machine, xml_get_sibling(itemnode.child, "color"), m_color);
+ parse_orientation(machine, xml_get_sibling(itemnode.child, "orientation"), m_orientation);
+
+ // sanity checks
+ if (strcmp(itemnode.name, "screen") == 0)
{
- /* x/y/width/height format */
- bounds->x0 = xml_get_attribute_float_with_subst(machine, boundsnode, "x", 0.0f);
- bounds->x1 = bounds->x0 + xml_get_attribute_float_with_subst(machine, boundsnode, "width", 1.0f);
- bounds->y0 = xml_get_attribute_float_with_subst(machine, boundsnode, "y", 0.0f);
- bounds->y1 = bounds->y0 + xml_get_attribute_float_with_subst(machine, boundsnode, "height", 1.0f);
+ if (m_screen == NULL)
+ throw emu_fatalerror("Layout references invalid screen index %d", index);
}
else
{
- fatalerror("Illegal bounds value in XML");
- return 1;
- }
-
- /* check for errors */
- if (bounds->x0 > bounds->x1 || bounds->y0 > bounds->y1)
- {
- fatalerror("Illegal bounds value in XML: (%f-%f)-(%f-%f)", bounds->x0, bounds->x1, bounds->y0, bounds->y1);
- return 1;
+ if (m_element == NULL)
+ throw emu_fatalerror("Layout item of type %s require an element tag", itemnode.name);
}
- return 0;
}
-/*-------------------------------------------------
- load_color - parse a color XML node
--------------------------------------------------*/
+//-------------------------------------------------
+// item - destructor
+//-------------------------------------------------
-static int load_color(running_machine &machine, xml_data_node *colornode, render_color *color)
+layout_view::item::~item()
{
- /* skip if nothing */
- if (colornode == NULL)
- {
- color->r = color->g = color->b = color->a = 1.0f;
- return 0;
- }
-
- /* parse out the data */
- color->r = xml_get_attribute_float_with_subst(machine, colornode, "red", 1.0);
- color->g = xml_get_attribute_float_with_subst(machine, colornode, "green", 1.0);
- color->b = xml_get_attribute_float_with_subst(machine, colornode, "blue", 1.0);
- color->a = xml_get_attribute_float_with_subst(machine, colornode, "alpha", 1.0);
-
- /* check for errors */
- if (color->r < 0.0 || color->r > 1.0 || color->g < 0.0 || color->g > 1.0 ||
- color->b < 0.0 || color->b > 1.0 || color->a < 0.0 || color->a > 1.0)
- {
- fatalerror("Illegal ARGB color value in XML: %f,%f,%f,%f", color->r, color->g, color->b, color->a);
- return 1;
- }
- return 0;
}
-/*-------------------------------------------------
- load_orientation - parse an orientation XML
- node
--------------------------------------------------*/
+//-------------------------------------------------
+// state - fetch state based on configured source
+//-------------------------------------------------
-static int load_orientation(running_machine &machine, xml_data_node *orientnode, int *orientation)
+int layout_view::item::state() const
{
- int rotate;
-
- /* skip if nothing */
- if (orientnode == NULL)
+ int state = 0;
+
+ assert(m_element != NULL);
+
+ // if configured to an output, fetch the output value
+ if (m_output_name[0] != 0)
+ state = output_get_value(m_output_name);
+
+ // if configured to an input, fetch the input value
+ else if (m_input_tag[0] != 0)
{
- *orientation = ROT0;
- return 0;
+ const input_field_config *field = input_field_by_tag_and_mask(m_element->machine().m_portlist, m_input_tag, m_input_mask);
+ if (field != NULL)
+ state = ((input_port_read_safe(&m_element->machine(), m_input_tag, 0) ^ field->defvalue) & m_input_mask) ? 1 : 0;
}
-
- /* parse out the data */
- rotate = xml_get_attribute_int_with_subst(machine, orientnode, "rotate", 0);
- switch (rotate)
- {
- case 0: *orientation = ROT0; break;
- case 90: *orientation = ROT90; break;
- case 180: *orientation = ROT180; break;
- case 270: *orientation = ROT270; break;
- default:
- fatalerror("Invalid rotation in XML orientation node: %d", rotate);
- return 1;
- }
- if (strcmp("yes", xml_get_attribute_string_with_subst(machine, orientnode, "swapxy", "no")) == 0)
- *orientation ^= ORIENTATION_SWAP_XY;
- if (strcmp("yes", xml_get_attribute_string_with_subst(machine, orientnode, "flipx", "no")) == 0)
- *orientation ^= ORIENTATION_FLIP_X;
- if (strcmp("yes", xml_get_attribute_string_with_subst(machine, orientnode, "flipy", "no")) == 0)
- *orientation ^= ORIENTATION_FLIP_Y;
- return 0;
+ return state;
}
-/*-------------------------------------------------
- layout_file_free - free memory for a
- layout_file and all of its subelements
--------------------------------------------------*/
-
-void layout_file_free(layout_file *file)
-{
- /* free each element in the list */
- while (file->elemlist != NULL)
- {
- layout_element *temp = file->elemlist;
- file->elemlist = temp->next;
- layout_element_free(temp);
- }
-
- /* free each layout */
- while (file->viewlist != NULL)
- {
- layout_view *temp = file->viewlist;
- file->viewlist = temp->next;
- layout_view_free(temp);
- }
-
- /* free the file itself */
- global_free(file);
-}
+//**************************************************************************
+// LAYOUT FILE
+//**************************************************************************
-/*-------------------------------------------------
- layout_view_free - free memory for a
- layout_view and all of its subelements
--------------------------------------------------*/
+//-------------------------------------------------
+// layout_file - constructor
+//-------------------------------------------------
-static void layout_view_free(layout_view *view)
+layout_file::layout_file(running_machine &machine, xml_data_node &rootnode, const char *dirname)
+ : m_next(NULL),
+ m_elemlist(machine.m_respool),
+ m_viewlist(machine.m_respool)
{
- int layer;
+ // find the layout node
+ xml_data_node *mamelayoutnode = xml_get_sibling(rootnode.child, "mamelayout");
+ if (mamelayoutnode == NULL)
+ throw emu_fatalerror("Invalid XML file: missing mamelayout node");
- /* for each layer, free each item in that layer */
- for (layer = 0; layer < ITEM_LAYER_MAX; layer++)
- while (view->itemlist[layer] != NULL)
- {
- view_item *temp = view->itemlist[layer];
- view->itemlist[layer] = temp->next;
- if (temp->output_name != NULL)
- global_free(temp->output_name);
- if (temp->input_tag != NULL)
- global_free(temp->input_tag);
- global_free(temp);
- }
+ // validate the config data version
+ int version = xml_get_attribute_int(mamelayoutnode, "version", 0);
+ if (version != LAYOUT_VERSION)
+ throw emu_fatalerror("Invalid XML file: unsupported version");
- /* free the view itself */
- if (view->name != NULL)
- global_free((void *)view->name);
- global_free(view);
+ // parse all the elements
+ for (xml_data_node *elemnode = xml_get_sibling(mamelayoutnode->child, "element"); elemnode != NULL; elemnode = xml_get_sibling(elemnode->next, "element"))
+ m_elemlist.append(*auto_alloc(&machine, layout_element(machine, *elemnode, dirname)));
+
+ // parse all the views
+ for (xml_data_node *viewnode = xml_get_sibling(mamelayoutnode->child, "view"); viewnode != NULL; viewnode = xml_get_sibling(viewnode->next, "view"))
+ m_viewlist.append(*auto_alloc(&machine, layout_view(machine, *viewnode, m_elemlist)));
}
-/*-------------------------------------------------
- layout_element_free - free memory for a
- layout_element and its components
--------------------------------------------------*/
+//-------------------------------------------------
+// ~layout_file - destructor
+//-------------------------------------------------
-static void layout_element_free(layout_element *element)
+layout_file::~layout_file()
{
- /* free all allocated components */
- while (element->complist != NULL)
- {
- element_component *temp = element->complist;
- element->complist = temp->next;
- if (temp->string != NULL)
- global_free(temp->string);
- if (temp->dirname != NULL)
- global_free(temp->dirname);
- if (temp->imagefile != NULL)
- global_free(temp->imagefile);
- if (temp->alphafile != NULL)
- global_free(temp->alphafile);
- global_free(temp->bitmap);
- global_free(temp);
- }
-
- /* free all textures */
- if (element->elemtex != NULL)
- {
- int state;
-
- /* loop over all states and free their textures */
- for (state = 0; state <= element->maxstate; state++)
- element->machine->render().texture_free(element->elemtex[state].texture);
-
- global_free(element->elemtex);
- }
-
- /* free the element itself */
- if (element->name != NULL)
- global_free(element->name);
- global_free(element);
}
diff --git a/src/emu/rendlay.h b/src/emu/rendlay.h
index 1a040c85f10..2b25d11d5be 100644
--- a/src/emu/rendlay.h
+++ b/src/emu/rendlay.h
@@ -4,8 +4,36 @@
Core rendering layout parser and manager.
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -14,206 +42,281 @@
#include "render.h"
-#include <math.h>
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-
-/***************************************************************************
-
- Theory of operation
- -------------------
-
- A render "target" is described by 5 parameters:
-
- - width = width, in pixels
- - height = height, in pixels
- - bpp = depth, in bits per pixel
- - orientation = orientation of the target
- - pixel_aspect = aspect ratio of the pixels
-
- Width, height, and bpp are self-explanatory. The remaining parameters
- need some additional explanation.
-
- Regarding orientation, there are three orientations that need to be
- dealt with: target orientation, UI orientation, and game orientation.
- In the current model, the UI orientation tracks the target orientation
- so that the UI is (in theory) facing the correct direction. The game
- orientation is specified by the game driver and indicates how the
- game and artwork are rotated.
-
- Regarding pixel_aspect, this is the aspect ratio of the individual
- pixels, not the aspect ratio of the screen. You can determine this by
- dividing the aspect ratio of the screen by the aspect ratio of the
- resolution. For example, a 4:3 screen displaying 640x480 gives a
- pixel aspect ratio of (4/3)/(640/480) = 1.0, meaning the pixels are
- square. That same screen displaying 1280x1024 would have a pixel
- aspect ratio of (4/3)/(1280/1024) = 1.06666, meaning the pixels are
- slightly wider than they are tall.
-
- Artwork is always assumed to be a 1.0 pixel aspect ratio. The game
- screens themselves can be variable aspect ratios.
-
-***************************************************************************/
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-enum
+enum item_layer
{
- ITEM_LAYER_BACKDROP = 0,
+ ITEM_LAYER_FIRST = 0,
+ ITEM_LAYER_BACKDROP = ITEM_LAYER_FIRST,
ITEM_LAYER_SCREEN,
ITEM_LAYER_OVERLAY,
ITEM_LAYER_BEZEL,
ITEM_LAYER_MAX
};
+DECLARE_ENUM_OPERATORS(item_layer);
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-typedef struct _element_component element_component;
-typedef struct _element_texture element_texture;
-typedef struct _layout_element layout_element;
-typedef struct _view_item_state view_item_state;
-typedef struct _view_item view_item;
-typedef struct _layout_view layout_view;
-typedef struct _layout_file layout_file;
-
-/* an element_texture encapsulates a texture for a given element in a given state */
-struct _element_texture
-{
- layout_element * element; /* pointer back to the element */
- render_texture * texture; /* texture for this state */
- int state; /* associated state number */
-};
+// ======================> layout_element
-/* a layout_element is a single named element, which may have multiple components */
-struct _layout_element
+// a layout_element is a single named element, which may have multiple components
+class layout_element
{
- layout_element * next; /* link to next element */
- running_machine * machine;
- const char * name; /* name of this element */
- element_component * complist; /* head of the list of components */
- int defstate; /* default state of this element */
- int maxstate; /* maximum state value for all components */
- element_texture * elemtex; /* array of element textures used for managing the scaled bitmaps */
+ friend class simple_list<layout_element>;
+
+public:
+ // construction/destruction
+ layout_element(running_machine &machine, xml_data_node &elemnode, const char *dirname);
+ virtual ~layout_element();
+
+ // getters
+ layout_element *next() const { return m_next; }
+ const char *name() const { return m_name; }
+ running_machine &machine() const { return m_machine; }
+ int default_state() const { return m_defstate; }
+ int maxstate() const { return m_maxstate; }
+ render_texture *state_texture(int state);
+
+private:
+ // a component represents an image, rectangle, or disk in an element
+ class component
+ {
+ friend class layout_element;
+ friend class simple_list<component>;
+
+ public:
+ // construction/destruction
+ component(running_machine &machine, xml_data_node &compnode, const char *dirname);
+ ~component();
+
+ // getters
+ component *next() const { return m_next; }
+ const render_bounds &bounds() const { return m_bounds; }
+
+ // operations
+ void draw(running_machine &machine, bitmap_t &dest, const rectangle &bounds, int state);
+
+ private:
+ // component types
+ enum component_type
+ {
+ CTYPE_INVALID = 0,
+ CTYPE_IMAGE,
+ CTYPE_RECT,
+ CTYPE_DISK,
+ CTYPE_TEXT,
+ CTYPE_LED7SEG,
+ CTYPE_LED14SEG,
+ CTYPE_LED16SEG,
+ CTYPE_LED14SEGSC,
+ CTYPE_LED16SEGSC,
+ CTYPE_DOTMATRIX,
+ CTYPE_MAX
+ };
+
+ // helpers
+ void draw_rect(bitmap_t &dest, const rectangle &bounds);
+ void draw_disk(bitmap_t &dest, const rectangle &bounds);
+ void draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds);
+ bitmap_t *load_bitmap();
+ void draw_led7seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led14seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led14segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led16seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led16segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color);
+ void draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color);
+ void draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color);
+ void draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color);
+ void draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color);
+ void draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void apply_skew(bitmap_t &dest, int skewwidth);
+
+ // internal state
+ component * m_next; // link to next component
+ component_type m_type; // type of component
+ int m_state; // state where this component is visible (-1 means all states)
+ render_bounds m_bounds; // bounds of the element
+ render_color m_color; // color of the element
+ astring m_string; // string for text components
+ bitmap_t * m_bitmap; // source bitmap for images
+ astring m_dirname; // directory name of image file (for lazy loading)
+ astring m_imagefile; // name of the image file (for lazy loading)
+ astring m_alphafile; // name of the alpha file (for lazy loading)
+ bool m_hasalpha; // is there any alpha component present?
+ };
+
+ // a texture encapsulates a texture for a given element in a given state
+ class texture
+ {
+ public:
+ texture();
+ ~texture();
+
+ layout_element * m_element; // pointer back to the element
+ render_texture * m_texture; // texture for this state
+ int m_state; // associated state number
+ };
+
+ // internal helpers
+ static void element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+
+ // internal state
+ layout_element * m_next; // link to next element
+ running_machine & m_machine; // reference to the owning machine
+ astring m_name; // name of this element
+ simple_list<component> m_complist; // list of components
+ int m_defstate; // default state of this element
+ int m_maxstate; // maximum state value for all components
+ texture * m_elemtex; // array of element textures used for managing the scaled bitmaps
};
-/* a view_item_state contains the string-tagged state of a view item */
-struct _view_item_state
-{
- view_item_state * next; /* pointer to the next one */
- const char * name; /* string that was set */
- int curstate; /* current state */
-};
-
+// ======================> layout_view
-/* a view_item is a single backdrop, screen, overlay, or bezel item */
-struct _view_item
+// a layout_view encapsulates a named list of items
+class layout_view
{
- view_item * next; /* link to next item */
- layout_element * element; /* pointer to the associated element (non-screens only) */
- const char * output_name; /* name of this item */
- const char * input_tag; /* input tag of this item */
- UINT32 input_mask; /* input mask of this item */
- int index; /* index for this item (screens only) */
- int orientation; /* orientation of this item */
- render_bounds bounds; /* bounds of the item */
- render_bounds rawbounds; /* raw (original) bounds of the item */
- render_color color; /* color of the item */
+ friend class simple_list<layout_view>;
+
+public:
+ // an item is a single backdrop, screen, overlay, or bezel item
+ class item
+ {
+ friend class layout_view;
+ friend class simple_list<item>;
+
+ public:
+ // construction/destruction
+ item(running_machine &machine, xml_data_node &itemnode, simple_list<layout_element> &elemlist);
+ virtual ~item();
+
+ // getters
+ item *next() const { return m_next; }
+ layout_element *element() const { return m_element; }
+ screen_device *screen() { return m_screen; }
+ const render_bounds &bounds() const { return m_bounds; }
+ const render_color &color() const { return m_color; }
+ int orientation() const { return m_orientation; }
+ render_container *screen_container(running_machine &machine) const { return (m_screen != NULL) ? &m_screen->container() : NULL; }
+ bool has_input() const { return bool(m_input_tag); }
+ const char *input_tag_and_mask(UINT32 &mask) const { mask = m_input_mask; return m_input_tag; }
+
+ // fetch state based on configured source
+ int state() const;
+
+ private:
+ // internal state
+ item * m_next; // link to next item
+ layout_element * m_element; // pointer to the associated element (non-screens only)
+ astring m_output_name; // name of this item
+ astring m_input_tag; // input tag of this item
+ UINT32 m_input_mask; // input mask of this item
+ screen_device * m_screen; // pointer to screen
+ int m_orientation; // orientation of this item
+ render_bounds m_bounds; // bounds of the item
+ render_bounds m_rawbounds; // raw (original) bounds of the item
+ render_color m_color; // color of the item
+ };
+
+ // construction/destruction
+ layout_view(running_machine &machine, xml_data_node &viewnode, simple_list<layout_element> &elemlist);
+ virtual ~layout_view();
+
+ // getters
+ layout_view *next() const { return m_next; }
+ item *first_item(item_layer layer) const;
+ const char *name() const { return m_name; }
+ const render_screen_list &screens() const { return m_screens; }
+ bool layer_enabled(item_layer layer) const { return m_layenabled[layer]; }
+
+ //
+ bool has_art() const { return (m_backdrop_list.count() + m_overlay_list.count() + m_bezel_list.count() != 0); }
+ float effective_aspect(render_layer_config config) const { return (config.zoom_to_screen() && m_screens.count() != 0) ? m_scraspect : m_aspect; }
+
+ // operations
+ void recompute(render_layer_config layerconfig);
+
+private:
+ // internal state
+ layout_view * m_next; // pointer to next layout in the list
+ astring m_name; // name of the layout
+ float m_aspect; // X/Y of the layout
+ float m_scraspect; // X/Y of the screen areas
+ render_screen_list m_screens; // list of active screens
+ render_bounds m_bounds; // computed bounds of the view
+ render_bounds m_scrbounds; // computed bounds of the screens within the view
+ render_bounds m_expbounds; // explicit bounds of the view
+ bool m_layenabled[ITEM_LAYER_MAX]; // is this layer enabled?
+ simple_list<item> m_backdrop_list; // list of backdrop items
+ simple_list<item> m_screen_list; // list of screen items
+ simple_list<item> m_overlay_list; // list of overlay items
+ simple_list<item> m_bezel_list; // list of bezel items
};
-/* a layout_view encapsulates a named list of items */
-struct _layout_view
-{
- layout_view * next; /* pointer to next layout in the list */
- const char * name; /* name of the layout */
- float aspect; /* X/Y of the layout */
- float scraspect; /* X/Y of the screen areas */
- UINT32 screens; /* bitmask of screens used */
- render_bounds bounds; /* computed bounds of the view */
- render_bounds scrbounds; /* computed bounds of the screens within the view */
- render_bounds expbounds; /* explicit bounds of the view */
- UINT8 layenabled[ITEM_LAYER_MAX]; /* is this layer enabled? */
- view_item * itemlist[ITEM_LAYER_MAX]; /* list of layout items for each layer */
-};
-
+// ======================> layout_file
-/* a layout_file consists of a list of elements and a list of views */
-struct _layout_file
+// a layout_file consists of a list of elements and a list of views
+class layout_file
{
- layout_file * next; /* pointer to the next file in the list */
- layout_element * elemlist; /* list of shared layout elements */
- layout_view * viewlist; /* list of views */
+ friend class simple_list<layout_file>;
+
+public:
+ // construction/destruction
+ layout_file(running_machine &machine, xml_data_node &rootnode, const char *dirname);
+ virtual ~layout_file();
+
+ // getters
+ layout_file *next() const { return m_next; }
+ layout_element *first_element() const { return m_elemlist.first(); }
+ layout_view *first_view() const { return m_viewlist.first(); }
+
+private:
+ // internal state
+ layout_file * m_next; // pointer to the next file in the list
+ simple_list<layout_element> m_elemlist; // list of shared layout elements
+ simple_list<layout_view> m_viewlist; // list of views
};
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* ----- layout views ----- */
-void layout_view_recompute(layout_view *view, int layerconfig);
-
-
-/* ----- layout file parsing ----- */
-layout_file *layout_file_load(running_machine &machine, const char *dirname, const char *filename);
-void layout_file_free(layout_file *file);
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+// single screen layouts
+extern const char layout_horizont[]; // horizontal 4:3 screens
+extern const char layout_vertical[]; // vertical 4:3 screens
+// dual screen layouts
+extern const char layout_dualhsxs[]; // dual 4:3 screens side-by-side
+extern const char layout_dualhovu[]; // dual 4:3 screens above and below
+extern const char layout_dualhuov[]; // dual 4:3 screens below and above
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
-
-/* single screen layouts */
-extern const char layout_horizont[]; /* horizontal 4:3 screens */
-extern const char layout_vertical[]; /* vertical 4:3 screens */
-
-/* dual screen layouts */
-extern const char layout_dualhsxs[]; /* dual 4:3 screens side-by-side */
-extern const char layout_dualhovu[]; /* dual 4:3 screens above and below */
-extern const char layout_dualhuov[]; /* dual 4:3 screens below and above */
-
-/* triple screen layouts */
-extern const char layout_triphsxs[]; /* triple 4:3 screens side-by-side */
-
-/* generic color overlay layouts */
-extern const char layout_ho20ffff[]; /* horizontal 4:3 with 20,FF,FF color overlay */
-extern const char layout_ho2eff2e[]; /* horizontal 4:3 with 2E,FF,2E color overlay */
-extern const char layout_ho4f893d[]; /* horizontal 4:3 with 4F,89,3D color overlay */
-extern const char layout_ho88ffff[]; /* horizontal 4:3 with 88,FF,FF color overlay */
-extern const char layout_hoa0a0ff[]; /* horizontal 4:3 with A0,A0,FF color overlay */
-extern const char layout_hoffe457[]; /* horizontal 4:3 with FF,E4,57 color overlay */
-extern const char layout_hoffff20[]; /* horizontal 4:3 with FF,FF,20 color overlay */
-extern const char layout_voffff20[]; /* vertical 4:3 with FF,FF,20 color overlay */
-
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- layout_view_has_art - true if a render_view contains
- any non-screen elements
--------------------------------------------------*/
-
-INLINE int layout_view_has_art(layout_view *view)
-{
- return (view->itemlist[ITEM_LAYER_BACKDROP] != 0 ||
- view->itemlist[ITEM_LAYER_OVERLAY] != 0 ||
- view->itemlist[ITEM_LAYER_BEZEL] != 0);
-}
+// triple screen layouts
+extern const char layout_triphsxs[]; // triple 4:3 screens side-by-side
+// generic color overlay layouts
+extern const char layout_ho20ffff[]; // horizontal 4:3 with 20,FF,FF color overlay
+extern const char layout_ho2eff2e[]; // horizontal 4:3 with 2E,FF,2E color overlay
+extern const char layout_ho4f893d[]; // horizontal 4:3 with 4F,89,3D color overlay
+extern const char layout_ho88ffff[]; // horizontal 4:3 with 88,FF,FF color overlay
+extern const char layout_hoa0a0ff[]; // horizontal 4:3 with A0,A0,FF color overlay
+extern const char layout_hoffe457[]; // horizontal 4:3 with FF,E4,57 color overlay
+extern const char layout_hoffff20[]; // horizontal 4:3 with FF,FF,20 color overlay
+extern const char layout_voffff20[]; // vertical 4:3 with FF,FF,20 color overlay
-#endif /* __RENDLAY_H__ */
+#endif // __RENDLAY_H__
diff --git a/src/emu/rendutil.c b/src/emu/rendutil.c
index 8377a395a8f..c6c9dea23fc 100644
--- a/src/emu/rendutil.c
+++ b/src/emu/rendutil.c
@@ -23,8 +23,8 @@
/* utilities */
static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
-static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha);
-static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha);
+static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
+static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
@@ -560,7 +560,7 @@ void render_line_to_quad(const render_bounds *bounds, float width, render_bounds
bitmap_t
-------------------------------------------------*/
-bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha)
+bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha)
{
bitmap_t *bitmap = NULL;
file_error filerr;
@@ -636,7 +636,7 @@ bitmap_t *render_load_png(const char *path, const char *dirname, const char *fil
bitmap
-------------------------------------------------*/
-static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha)
+static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
{
UINT8 accumalpha = 0xff;
UINT8 *src;
@@ -701,7 +701,7 @@ static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasal
to the alpha channel of a bitmap
-------------------------------------------------*/
-static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha)
+static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
{
UINT8 accumalpha = 0xff;
UINT8 *src;
diff --git a/src/emu/rendutil.h b/src/emu/rendutil.h
index 1331dd1282f..e6d1a423842 100644
--- a/src/emu/rendutil.h
+++ b/src/emu/rendutil.h
@@ -28,7 +28,7 @@ void render_resample_argb_bitmap_hq(void *dest, UINT32 drowpixels, UINT32 dwidth
int render_clip_line(render_bounds *bounds, const render_bounds *clip);
int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1);
-bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha);
+bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha);
diff --git a/src/emu/video.c b/src/emu/video.c
index 2ee3790864b..dbd52f117ee 100644
--- a/src/emu/video.c
+++ b/src/emu/video.c
@@ -312,7 +312,11 @@ void video_init(running_machine *machine)
if (global.snap_native)
{
global.snap_target = machine->render().target_alloc(layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN);
- global.snap_target->set_layer_config(0);
+ global.snap_target->set_backdrops_enabled(false);
+ global.snap_target->set_overlays_enabled(false);
+ global.snap_target->set_bezels_enabled(false);
+ global.snap_target->set_screen_overlay_enabled(false);
+ global.snap_target->set_zoom_to_screen(false);
}
/* other targets select the specified view and turn off effects */
@@ -1603,13 +1607,19 @@ int video_get_view_for_target(running_machine *machine, render_target *target, c
/* if we have enough targets to be one per screen, assign in order */
if (numtargets >= scrcount)
{
+ int index = target->index() % scrcount;
+ screen_device *screen;
+ for (screen = screen_first(*machine); screen != NULL; screen = screen_next(screen))
+ if (index-- == 0)
+ break;
+
/* find the first view with this screen and this screen only */
for (viewindex = 0; ; viewindex++)
{
- UINT32 viewscreens = target->view_screens(viewindex);
- if (viewscreens == (1 << targetindex))
+ const render_screen_list &viewscreens = target->view_screens(viewindex);
+ if (viewscreens.count() == 1 && viewscreens.contains(*screen))
break;
- if (viewscreens == 0)
+ if (viewscreens.count() == 0)
{
viewindex = -1;
break;
@@ -1622,11 +1632,18 @@ int video_get_view_for_target(running_machine *machine, render_target *target, c
{
for (viewindex = 0; ; viewindex++)
{
- UINT32 viewscreens = target->view_screens(viewindex);
- if (viewscreens == (1 << scrcount) - 1)
- break;
- if (viewscreens == 0)
+ const render_screen_list &viewscreens = target->view_screens(viewindex);
+ if (viewscreens.count() == 0)
break;
+ if (viewscreens.count() >= scrcount)
+ {
+ screen_device *screen;
+ for (screen = screen_first(*machine); screen != NULL; screen = screen_next(screen))
+ if (!viewscreens.contains(*screen))
+ break;
+ if (screen == NULL)
+ break;
+ }
}
}
}
@@ -1942,9 +1959,6 @@ screen_device::~screen_device()
void screen_device::device_start()
{
- // get and validate that the container for this screen exists
- m_container = m_machine.render().container_for_screen(this);
-
// configure the default cliparea
render_container::user_settings settings;
m_container->get_user_settings(settings);
diff --git a/src/emu/video.h b/src/emu/video.h
index 3cd0d6142d8..8ffcc82537a 100644
--- a/src/emu/video.h
+++ b/src/emu/video.h
@@ -141,6 +141,7 @@ private:
class screen_device : public device_t
{
friend class screen_device_config;
+ friend class render_manager;
friend resource_pool_object<screen_device>::~resource_pool_object();
// construction/destruction
@@ -199,6 +200,7 @@ private:
virtual void device_post_load();
// internal helpers
+ void set_container(render_container &container) { m_container = &container; }
void realloc_screen_bitmaps();
static TIMER_CALLBACK( static_vblank_begin_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_begin_callback(); }
diff --git a/src/osd/windows/video.h b/src/osd/windows/video.h
index 98396188547..afb8ac65049 100644
--- a/src/osd/windows/video.h
+++ b/src/osd/windows/video.h
@@ -42,6 +42,8 @@
#ifndef __WIN_VIDEO__
#define __WIN_VIDEO__
+#include "render.h"
+
//============================================================
// CONSTANTS
@@ -90,7 +92,7 @@ struct _win_video_config
int prescale; // prescale factor
int keepaspect; // keep aspect ratio
int numscreens; // number of screens
- int layerconfig; // default configuration of layers
+ render_layer_config layerconfig; // default configuration of layers
// per-window configuration
win_window_config window[MAX_WINDOWS]; // configuration data per-window
diff --git a/src/osd/windows/window.c b/src/osd/windows/window.c
index b9ee2aabf74..b8c82315822 100644
--- a/src/osd/windows/window.c
+++ b/src/osd/windows/window.c
@@ -718,7 +718,8 @@ static void winwindow_video_window_destroy(win_window_info *window)
void winwindow_video_window_update(win_window_info *window)
{
- int targetview, targetorient, targetlayerconfig;
+ int targetview, targetorient;
+ render_layer_config targetlayerconfig;
assert(GetCurrentThreadId() == main_threadid);
diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h
index 7e743828bd3..64786a2ea75 100644
--- a/src/osd/windows/window.h
+++ b/src/osd/windows/window.h
@@ -100,7 +100,7 @@ struct _win_window_info
render_target * target;
int targetview;
int targetorient;
- int targetlayerconfig;
+ render_layer_config targetlayerconfig;
render_primitive_list *primlist;
// input info