Use std::map for mapping XML tag name to layout component creation function - makes the code simpler and easier to read as well as being more scalable

Fix problem using layout_element::texture in vector - destructor frees resources but generated copy/assignment operators don't release them, leading to a problem any time vector expands or element is added/removed anywhere but end
This commit is contained in:
Vas Crabb 2016-07-02 14:18:44 +10:00
parent 491ecdb025
commit 4142ecd794
2 changed files with 109 additions and 84 deletions

View File

@ -43,18 +43,23 @@
***************************************************************************/ ***************************************************************************/
#ifndef __RENDER_H__ #ifndef MAME_EMU_RENDER_H
#define __RENDER_H__ #define MAME_EMU_RENDER_H
//#include "osdepend.h" //#include "osdepend.h"
#include <math.h>
#include <mutex>
#include "emu.h" #include "emu.h"
//#include "bitmap.h" //#include "bitmap.h"
//#include "screen.h" //#include "screen.h"
#include <math.h>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
//************************************************************************** //**************************************************************************
// CONSTANTS // CONSTANTS
//************************************************************************** //**************************************************************************
@ -651,6 +656,8 @@ private:
class component class component
{ {
public: public:
typedef std::unique_ptr<component> ptr;
// construction/destruction // construction/destruction
component(running_machine &machine, xml_data_node &compnode, const char *dirname); component(running_machine &machine, xml_data_node &compnode, const char *dirname);
virtual ~component() = default; virtual ~component() = default;
@ -907,24 +914,37 @@ private:
{ {
public: public:
texture(); texture();
texture(texture const &that) = delete;
texture(texture &&that);
~texture(); ~texture();
texture &operator=(texture const &that) = delete;
texture &operator=(texture &&that);
layout_element * m_element; // pointer back to the element layout_element * m_element; // pointer back to the element
render_texture * m_texture; // texture for this state render_texture * m_texture; // texture for this state
int m_state; // associated state number int m_state; // associated state number
}; };
typedef component::ptr (*make_component_func)(running_machine &machine, xml_data_node &compnode, const char *dirname);
typedef std::map<std::string, make_component_func> make_component_map;
// internal helpers // internal helpers
static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param); static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
template <typename T> static component::ptr make_component(running_machine &machine, xml_data_node &compnode, const char *dirname);
template <int D> static component::ptr make_dotmatrix_component(running_machine &machine, xml_data_node &compnode, const char *dirname);
static make_component_map const s_make_component; // maps component XML names to creator functions
// internal state // internal state
layout_element * m_next; // link to next element layout_element * m_next; // link to next element
running_machine & m_machine; // reference to the owning machine running_machine & m_machine; // reference to the owning machine
std::string m_name; // name of this element std::string m_name; // name of this element
std::vector<std::unique_ptr<component>> m_complist; // list of components std::vector<component::ptr> m_complist; // list of components
int m_defstate; // default state of this element int m_defstate; // default state of this element
int m_maxstate; // maximum state value for all components int m_maxstate; // maximum state value for all components
std::vector<texture> m_elemtex; // array of element textures used for managing the scaled bitmaps std::vector<texture> m_elemtex; // array of element textures used for managing the scaled bitmaps
}; };
@ -1269,4 +1289,4 @@ private:
simple_list<render_container> m_screen_container_list; // list of containers for the screen simple_list<render_container> m_screen_container_list; // list of containers for the screen
}; };
#endif // __RENDER_H__ #endif // MAME_EMU_RENDER_H

View File

@ -400,6 +400,24 @@ static void parse_orientation(running_machine &machine, xml_data_node *orientnod
// LAYOUT ELEMENT // LAYOUT ELEMENT
//************************************************************************** //**************************************************************************
layout_element::make_component_map const layout_element::s_make_component{
{ "image", &make_component<image_component> },
{ "text", &make_component<text_component> },
{ "dotmatrix", &make_dotmatrix_component<8> },
{ "dotmatrix5dot", &make_dotmatrix_component<5> },
{ "dotmatrixdot", &make_dotmatrix_component<1> },
{ "simplecounter", &make_component<simplecounter_component> },
{ "reel", &make_component<reel_component> },
{ "led7seg", &make_component<led7seg_component> },
{ "led8seg_gts1", &make_component<led8seg_gts1_component> },
{ "led14seg", &make_component<led14seg_component> },
{ "led14segsc", &make_component<led14segsc_component> },
{ "led16seg", &make_component<led16seg_component> },
{ "led16segsc", &make_component<led16segsc_component> },
{ "rect", &make_component<rect_component> },
{ "disk", &make_component<disk_component> }
};
//------------------------------------------------- //-------------------------------------------------
// layout_element - constructor // layout_element - constructor
//------------------------------------------------- //-------------------------------------------------
@ -422,82 +440,25 @@ layout_element::layout_element(running_machine &machine, xml_data_node &elemnode
// parse components in order // parse components in order
bool first = true; bool first = true;
render_bounds bounds = { 0 }; render_bounds bounds = { 0 };
for (xml_data_node *compnode = elemnode.child; compnode != nullptr; compnode = compnode->next) for (auto compnode = elemnode.child; compnode; compnode = compnode->next)
{ {
std::unique_ptr<component> newcomp; auto const make_func(s_make_component.find(compnode->name));
if (make_func == s_make_component.end())
// image nodes
if (strcmp(compnode->name, "image") == 0)
newcomp = std::make_unique<image_component>(machine, *compnode, dirname);
// text nodes
else if (strcmp(compnode->name, "text") == 0)
newcomp = std::make_unique<text_component>(machine, *compnode, dirname);
// dotmatrix nodes
else if (strcmp(compnode->name, "dotmatrix") == 0)
newcomp = std::make_unique<dotmatrix_component>(8, machine, *compnode, dirname);
else if (strcmp(compnode->name, "dotmatrix5dot") == 0)
newcomp = std::make_unique<dotmatrix_component>(5, machine, *compnode, dirname);
else if (strcmp(compnode->name, "dotmatrixdot") == 0)
newcomp = std::make_unique<dotmatrix_component>(1, machine, *compnode, dirname);
// simplecounter nodes
else if (strcmp(compnode->name, "simplecounter") == 0)
newcomp = std::make_unique<simplecounter_component>(machine, *compnode, dirname);
// fruit machine reels
else if (strcmp(compnode->name, "reel") == 0)
newcomp = std::make_unique<reel_component>(machine, *compnode, dirname);
// led7seg nodes
else if (strcmp(compnode->name, "led7seg") == 0)
newcomp = std::make_unique<led7seg_component>(machine, *compnode, dirname);
// led8seg_gts1 nodes
else if (strcmp(compnode->name, "led8seg_gts1") == 0)
newcomp = std::make_unique<led8seg_gts1_component>(machine, *compnode, dirname);
// led14seg nodes
else if (strcmp(compnode->name, "led14seg") == 0)
newcomp = std::make_unique<led14seg_component>(machine, *compnode, dirname);
// led14segsc nodes
else if (strcmp(compnode->name, "led14segsc") == 0)
newcomp = std::make_unique<led14segsc_component>(machine, *compnode, dirname);
// led16seg nodes
else if (strcmp(compnode->name, "led16seg") == 0)
newcomp = std::make_unique<led16seg_component>(machine, *compnode, dirname);
// led16segsc nodes
else if (strcmp(compnode->name, "led16segsc") == 0)
newcomp = std::make_unique<led16segsc_component>(machine, *compnode, dirname);
// rect nodes
else if (strcmp(compnode->name, "rect") == 0)
newcomp = std::make_unique<rect_component>(machine, *compnode, dirname);
// disk nodes
else if (strcmp(compnode->name, "disk") == 0)
newcomp = std::make_unique<disk_component>(machine, *compnode, dirname);
// error otherwise
else
throw emu_fatalerror("Unknown element component: %s", compnode->name); throw emu_fatalerror("Unknown element component: %s", compnode->name);
// insert the new component into the list
m_complist.emplace_back(make_func->second(machine, *compnode, dirname));
auto const &newcomp(*m_complist.back());
// accumulate bounds // accumulate bounds
if (first) if (first)
bounds = newcomp->bounds(); bounds = newcomp.bounds();
else else
union_render_bounds(&bounds, &newcomp->bounds()); union_render_bounds(&bounds, &newcomp.bounds());
first = false; first = false;
// determine the maximum state // determine the maximum state
m_maxstate = std::max(m_maxstate, newcomp->maxstate()); m_maxstate = std::max(m_maxstate, newcomp.maxstate());
// insert the new component into the list
m_complist.push_back(std::move(newcomp));
} }
if (!m_complist.empty()) if (!m_complist.empty())
@ -574,22 +535,52 @@ void layout_element::element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, c
} }
//-------------------------------------------------
// make_component - create component of given type
//-------------------------------------------------
template <typename T>
layout_element::component::ptr layout_element::make_component(running_machine &machine, xml_data_node &compnode, const char *dirname)
{
return std::make_unique<T>(machine, compnode, dirname);
}
//-------------------------------------------------
// make_component - create dotmatrix component
// with given vertical resolution
//-------------------------------------------------
template <int D>
layout_element::component::ptr layout_element::make_dotmatrix_component(running_machine &machine, xml_data_node &compnode, const char *dirname)
{
return std::make_unique<dotmatrix_component>(D, machine, compnode, dirname);
}
//************************************************************************** //**************************************************************************
// LAYOUT ELEMENT TEXTURE // LAYOUT ELEMENT TEXTURE
//************************************************************************** //**************************************************************************
//------------------------------------------------- //-------------------------------------------------
// texture - constructor // texture - constructors
//------------------------------------------------- //-------------------------------------------------
layout_element::texture::texture() layout_element::texture::texture()
: m_element(nullptr), : m_element(nullptr)
m_texture(nullptr), , m_texture(nullptr)
m_state(0) , m_state(0)
{ {
} }
layout_element::texture::texture(texture &&that) : texture()
{
operator=(std::move(that));
}
//------------------------------------------------- //-------------------------------------------------
// ~texture - destructor // ~texture - destructor
//------------------------------------------------- //-------------------------------------------------
@ -601,6 +592,20 @@ layout_element::texture::~texture()
} }
//-------------------------------------------------
// opearator= - move assignment
//-------------------------------------------------
layout_element::texture &layout_element::texture::operator=(texture &&that)
{
using std::swap;
swap(m_element, that.m_element);
swap(m_texture, that.m_texture);
swap(m_state, that.m_state);
return *this;
}
//************************************************************************** //**************************************************************************
// LAYOUT ELEMENT COMPONENT // LAYOUT ELEMENT COMPONENT