summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/rendlay.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-09-16 02:55:04 +1000
committer Vas Crabb <vas@vastheman.com>2020-09-16 02:55:04 +1000
commit6adc5080154819eb7543cb35328082280804fb07 (patch)
tree7212c7a3869d9d3c6b92a955b0d856f20b08b0a6 /src/emu/rendlay.cpp
parent523b1f11cffd7bfebb8ed0a7f35204f871dadeb0 (diff)
emu/rendlay.cpp: Added parameter animation and state masks.
Components may have multiple bounds and/or color child elements with state attributes, allowing for piecewise linear position/size/colour animation. Components may have a statemask attribute, allowing for things like using external images to draw a multi-segment LED/VFD display without requiring dozens of outputs for the individual lines or thousands of images for all possible states. (Texture caching still never releases anything, so MAME can still exceed the maximum number of textures, but that’s a separate issue.) Image components with alpha now blend over previously drawn components. Layouts have been changed to use yes/no for inputraw to match what's used for flipx/flipy. External layouts with 1/0 will still work, but complay.py will complain.
Diffstat (limited to 'src/emu/rendlay.cpp')
-rw-r--r--src/emu/rendlay.cpp723
1 files changed, 495 insertions, 228 deletions
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp
index 72c50a3db3b..198fa03998a 100644
--- a/src/emu/rendlay.cpp
+++ b/src/emu/rendlay.cpp
@@ -9,12 +9,14 @@
***************************************************************************/
#include "emu.h"
+#include "render.h"
+#include "rendlay.h"
#include "emuopts.h"
-#include "render.h"
#include "rendfont.h"
-#include "rendlay.h"
#include "rendutil.h"
+#include "video/rgbutil.h"
+
#include "vecstream.h"
#include "xmlfile.h"
@@ -938,12 +940,10 @@ layout_element::make_component_map const layout_element::s_make_component{
layout_element::layout_element(environment &env, util::xml::data_node const &elemnode, const char *dirname)
: m_machine(env.machine())
- , m_defstate(0)
- , m_maxstate(0)
+ , m_defstate(env.get_attribute_int(elemnode, "defstate", -1))
+ , m_statemask(0)
+ , m_foldhigh(false)
{
- // get the default state
- m_defstate = env.get_attribute_int(elemnode, "defstate", -1);
-
// parse components in order
bool first = true;
render_bounds bounds = { 0.0, 0.0, 0.0, 0.0 };
@@ -958,13 +958,15 @@ layout_element::layout_element(environment &env, util::xml::data_node const &ele
// accumulate bounds
if (first)
- bounds = newcomp.bounds();
+ bounds = newcomp.overall_bounds();
else
- union_render_bounds(bounds, newcomp.bounds());
+ union_render_bounds(bounds, newcomp.overall_bounds());
first = false;
// determine the maximum state
- m_maxstate = std::max(m_maxstate, newcomp.maxstate());
+ std::pair<int, bool> const wrap(newcomp.statewrap());
+ m_statemask |= wrap.first;
+ m_foldhigh = m_foldhigh || wrap.second;
}
if (!m_complist.empty())
@@ -972,8 +974,8 @@ layout_element::layout_element(environment &env, util::xml::data_node const &ele
// 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);
+ float xscale = 1.0F / (bounds.x1 - bounds.x0);
+ float yscale = 1.0F / (bounds.y1 - bounds.y0);
// normalize all the component bounds
for (component::ptr const &curcomp : m_complist)
@@ -981,7 +983,7 @@ layout_element::layout_element(environment &env, util::xml::data_node const &ele
}
// allocate an array of element textures for the states
- m_elemtex.resize(m_maxstate + 1);
+ m_elemtex.resize((m_statemask + 1) << (m_foldhigh ? 1 : 0));
}
@@ -1005,7 +1007,7 @@ layout_element::~layout_element()
layout_group::layout_group(util::xml::data_node const &groupnode)
: m_groupnode(groupnode)
- , m_bounds{ 0.0f, 0.0f, 0.0f, 0.0f }
+ , m_bounds{ 0.0F, 0.0F, 0.0F, 0.0F }
, m_bounds_resolved(false)
{
}
@@ -1284,8 +1286,12 @@ void layout_group::resolve_bounds(
render_texture *layout_element::state_texture(int state)
{
- assert(state <= m_maxstate);
- if (m_elemtex[state].m_texture == nullptr)
+ if (m_foldhigh && (state & ~m_statemask))
+ state = (state & m_statemask) | (((m_statemask << 1) | 1) & ~m_statemask);
+ else
+ state &= m_statemask;
+ assert(m_elemtex.size() > state);
+ if (!m_elemtex[state].m_texture)
{
m_elemtex[state].m_element = this;
m_elemtex[state].m_state = state;
@@ -1303,23 +1309,26 @@ render_texture *layout_element::state_texture(int state)
void layout_element::element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param)
{
- texture *elemtex = (texture *)param;
+ texture const &elemtex(*reinterpret_cast<texture const *>(param));
// iterate over components that are part of the current state
- for (auto &curcomp : elemtex->m_element->m_complist)
- if (curcomp->state() == -1 || curcomp->state() == elemtex->m_state)
+ for (auto const &curcomp : elemtex.m_element->m_complist)
+ {
+ if ((elemtex.m_state & curcomp->statemask()) == curcomp->stateval())
{
// get the local scaled bounds
+ render_bounds const compbounds(curcomp->bounds(elemtex.m_state));
rectangle bounds(
- render_round_nearest(curcomp->bounds().x0 * dest.width()),
- render_round_nearest(curcomp->bounds().x1 * dest.width()),
- render_round_nearest(curcomp->bounds().y0 * dest.height()),
- render_round_nearest(curcomp->bounds().y1 * dest.height()));
+ render_round_nearest(compbounds.x0 * dest.width()),
+ render_round_nearest(compbounds.x1 * dest.width()),
+ render_round_nearest(compbounds.y0 * dest.height()),
+ render_round_nearest(compbounds.y1 * dest.height()));
bounds &= dest.cliprect();
// based on the component type, add to the texture
- curcomp->draw(elemtex->m_element->machine(), dest, bounds, elemtex->m_state);
+ curcomp->draw(elemtex.m_element->machine(), dest, bounds, elemtex.m_state);
}
+ }
}
@@ -1330,13 +1339,10 @@ public:
// construction/destruction
image_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
: component(env, compnode, dirname)
- , m_hasalpha(false)
+ , m_dirname(dirname ? dirname : "")
+ , m_imagefile(env.get_attribute_string(compnode, "file", ""))
+ , m_alphafile(env.get_attribute_string(compnode, "alphafile", ""))
{
- if (dirname != nullptr)
- m_dirname = dirname;
- m_imagefile = env.get_attribute_string(compnode, "file", "");
- m_alphafile = env.get_attribute_string(compnode, "alphafile", "");
- m_file = std::make_unique<emu_file>(env.machine().options().art_path(), OPEN_FLAG_READ);
}
protected:
@@ -1344,19 +1350,56 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
if (!m_bitmap.valid())
- load_bitmap();
+ load_bitmap(machine);
- bitmap_argb32 destsub(dest, bounds);
- render_resample_argb_bitmap_hq(destsub, m_bitmap, color());
+ render_color const c(color(state));
+ if (m_hasalpha || (1.0F > c.a))
+ {
+ bitmap_argb32 tempbitmap(dest.width(), dest.height());
+ render_resample_argb_bitmap_hq(tempbitmap, m_bitmap, c);
+ for (s32 y0 = 0, y1 = bounds.top(); bounds.bottom() >= y1; ++y0, ++y1)
+ {
+ u32 const *src(&tempbitmap.pix(y0, 0));
+ u32 *dst(&dest.pix(y1, bounds.left()));
+ for (s32 x1 = bounds.left(); bounds.right() >= x1; ++x1, ++src, ++dst)
+ {
+ rgb_t const a(*src);
+ u32 const aa(a.a());
+ if (aa)
+ {
+ rgb_t const b(*dst);
+ u32 const ba(b.a());
+ if (ba)
+ {
+ u32 const ca((aa * 255) + (ba * (255 - aa)));
+ *dst = rgb_t(
+ u8(ca / 255),
+ u8(((a.r() * aa * 255) + (b.r() * ba * (255 - aa))) / ca),
+ u8(((a.g() * aa * 255) + (b.g() * ba * (255 - aa))) / ca),
+ u8(((a.b() * aa * 255) + (b.b() * ba * (255 - aa))) / ca));
+ }
+ else
+ {
+ *dst = *src;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ bitmap_argb32 destsub(dest, bounds);
+ render_resample_argb_bitmap_hq(destsub, m_bitmap, c);
+ }
}
private:
// internal helpers
- void load_bitmap()
+ void load_bitmap(running_machine &machine)
{
- assert(m_file != nullptr);
+ emu_file file(machine.options().art_path(), OPEN_FLAG_READ);
- ru_imgformat const format = render_detect_image(*m_file, m_dirname.c_str(), m_imagefile.c_str());
+ ru_imgformat const format = render_detect_image(file, m_dirname.c_str(), m_imagefile.c_str());
switch (format)
{
case RENDUTIL_IMGFORMAT_ERROR:
@@ -1364,18 +1407,18 @@ private:
case RENDUTIL_IMGFORMAT_PNG:
// load the basic bitmap
- m_hasalpha = render_load_png(m_bitmap, *m_file, m_dirname.c_str(), m_imagefile.c_str());
+ m_hasalpha = render_load_png(m_bitmap, file, m_dirname.c_str(), m_imagefile.c_str());
break;
default:
// try JPG
- render_load_jpeg(m_bitmap, *m_file, m_dirname.c_str(), m_imagefile.c_str());
+ render_load_jpeg(m_bitmap, file, m_dirname.c_str(), m_imagefile.c_str());
break;
}
// load the alpha bitmap if specified
if (m_bitmap.valid() && !m_alphafile.empty())
- render_load_png(m_bitmap, *m_file, m_dirname.c_str(), m_alphafile.c_str(), true);
+ render_load_png(m_bitmap, file, m_dirname.c_str(), m_alphafile.c_str(), true);
// if we can't load the bitmap, allocate a dummy one and report an error
if (!m_bitmap.valid())
@@ -1397,11 +1440,10 @@ private:
// internal state
bitmap_argb32 m_bitmap; // source bitmap for images
- std::string m_dirname; // directory name of image file (for lazy loading)
- std::unique_ptr<emu_file> m_file; // file object for reading image/alpha files
- std::string m_imagefile; // name of the image file (for lazy loading)
- std::string m_alphafile; // name of the alpha file (for lazy loading)
- bool m_hasalpha; // is there any alpha component present?
+ std::string const m_dirname; // directory name of image file (for lazy loading)
+ std::string const m_imagefile; // name of the image file (for lazy loading)
+ std::string const m_alphafile; // name of the alpha file (for lazy loading)
+ bool m_hasalpha = false; // is there any alpha component present?
};
@@ -1420,10 +1462,11 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
// compute premultiplied colors
- u32 const r = color().r * color().a * 255.0f;
- u32 const g = color().g * color().a * 255.0f;
- u32 const b = color().b * color().a * 255.0f;
- u32 const inva = (1.0f - color().a) * 255.0f;
+ render_color const c = color(state);
+ u32 const r = c.r * c.a * 255.0f;
+ u32 const g = c.g * c.a * 255.0f;
+ u32 const b = c.b * c.a * 255.0f;
+ u32 const inva = (1.0f - c.a) * 255.0f;
// iterate over X and Y
for (u32 y = bounds.top(); y <= bounds.bottom(); y++)
@@ -1466,10 +1509,11 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
// compute premultiplied colors
- u32 const r = color().r * color().a * 255.0f;
- u32 const g = color().g * color().a * 255.0f;
- u32 const b = color().b * color().a * 255.0f;
- u32 const inva = (1.0f - color().a) * 255.0f;
+ render_color const c(color(state));
+ u32 const r = c.r * c.a * 255.0f;
+ u32 const g = c.g * c.a * 255.0f;
+ u32 const b = c.b * c.a * 255.0f;
+ u32 const inva = (1.0f - c.a) * 255.0f;
// find the center
float const xcenter = float(bounds.xcenter());
@@ -1481,7 +1525,7 @@ protected:
// iterate over y
for (u32 y = bounds.top(); y <= bounds.bottom(); y++)
{
- float ycoord = ycenter - ((float)y + 0.5f);
+ float ycoord = ycenter - (float(y) + 0.5f);
float xval = xradius * sqrtf(1.0f - (ycoord * ycoord) * ooyradius2);
// compute left/right coordinates
@@ -1529,7 +1573,7 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
render_font *font = machine.render().font_alloc("default");
- draw_text(*font, dest, bounds, m_string.c_str(), m_textalign);
+ draw_text(*font, dest, bounds, m_string.c_str(), m_textalign, color(state));
machine.render().font_free(font);
}
@@ -1556,14 +1600,14 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- const rgb_t onpen = rgb_t(0xff,0xff,0xff,0xff);
- const rgb_t offpen = rgb_t(0x20,0xff,0xff,0xff);
+ rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
+ rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
// sizes for computation
- int bmwidth = 250;
- int bmheight = 400;
- int segwidth = 40;
- int skewwidth = 40;
+ int const bmwidth = 250;
+ int const bmheight = 400;
+ int const segwidth = 40;
+ int const skewwidth = 40;
// allocate a temporary bitmap for drawing
bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight);
@@ -1597,7 +1641,7 @@ protected:
draw_segment_decimal(tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, BIT(state, 7) ? onpen : offpen);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -1618,15 +1662,15 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- const rgb_t onpen = rgb_t(0xff,0xff,0xff,0xff);
- const rgb_t offpen = rgb_t(0x20,0xff,0xff,0xff);
- const rgb_t backpen = rgb_t(0x00,0x00,0x00,0x00);
+ rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
+ rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
+ rgb_t const backpen = rgb_t(0x00, 0x00, 0x00, 0x00);
// sizes for computation
- int bmwidth = 250;
- int bmheight = 400;
- int segwidth = 40;
- int skewwidth = 40;
+ int const bmwidth = 250;
+ int const bmheight = 400;
+ int const segwidth = 40;
+ int const skewwidth = 40;
// allocate a temporary bitmap for drawing
bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight);
@@ -1665,7 +1709,7 @@ protected:
apply_skew(tempbitmap, 40);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -1686,14 +1730,14 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- const rgb_t onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
- const rgb_t offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
+ rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
+ rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
// sizes for computation
- int bmwidth = 250;
- int bmheight = 400;
- int segwidth = 40;
- int skewwidth = 40;
+ int const bmwidth = 250;
+ int const bmheight = 400;
+ int const segwidth = 40;
+ int const skewwidth = 40;
// allocate a temporary bitmap for drawing
bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight);
@@ -1701,83 +1745,83 @@ protected:
// top bar
draw_segment_horizontal(tempbitmap,
- 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 0)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 0)) ? onpen : offpen);
// right-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 1)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 1)) ? onpen : offpen);
// right-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 2)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 2)) ? onpen : offpen);
// bottom bar
draw_segment_horizontal(tempbitmap,
- 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
- segwidth, (state & (1 << 3)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, (state & (1 << 3)) ? onpen : offpen);
// left-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 4)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 4)) ? onpen : offpen);
// left-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 5)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 5)) ? onpen : offpen);
// horizontal-middle-left bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
- segwidth, LINE_CAP_START, (state & (1 << 6)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (state & (1 << 6)) ? onpen : offpen);
// horizontal-middle-right bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
- segwidth, LINE_CAP_END, (state & (1 << 7)) ? onpen : offpen);
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (state & (1 << 7)) ? onpen : offpen);
// 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, (state & (1 << 8)) ? onpen : offpen);
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 8)) ? onpen : offpen);
// 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, (state & (1 << 9)) ? onpen : offpen);
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 9)) ? onpen : offpen);
// 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, (state & (1 << 10)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 10)) ? onpen : offpen);
// 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, (state & (1 << 11)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 11)) ? onpen : offpen);
// 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, (state & (1 << 12)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 12)) ? onpen : offpen);
// 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, (state & (1 << 13)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 13)) ? onpen : offpen);
// apply skew
apply_skew(tempbitmap, 40);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -1899,7 +1943,7 @@ protected:
apply_skew(tempbitmap, 40);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -1920,14 +1964,14 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- const rgb_t onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
- const rgb_t offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
+ rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
+ rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
// sizes for computation
- int bmwidth = 250;
- int bmheight = 400;
- int segwidth = 40;
- int skewwidth = 40;
+ int const bmwidth = 250;
+ int const bmheight = 400;
+ int const segwidth = 40;
+ int const skewwidth = 40;
// allocate a temporary bitmap for drawing, adding some extra space for the tail
bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight + segwidth);
@@ -1935,92 +1979,94 @@ protected:
// top bar
draw_segment_horizontal(tempbitmap,
- 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 0)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 0)) ? onpen : offpen);
// right-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 1)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 1)) ? onpen : offpen);
// right-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 2)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 2)) ? onpen : offpen);
// bottom bar
draw_segment_horizontal(tempbitmap,
- 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
- segwidth, (state & (1 << 3)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, (state & (1 << 3)) ? onpen : offpen);
// left-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 4)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 4)) ? onpen : offpen);
// left-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 5)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 5)) ? onpen : offpen);
// horizontal-middle-left bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
- segwidth, LINE_CAP_START, (state & (1 << 6)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (state & (1 << 6)) ? onpen : offpen);
// horizontal-middle-right bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
- segwidth, LINE_CAP_END, (state & (1 << 7)) ? onpen : offpen);
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (state & (1 << 7)) ? onpen : offpen);
// 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, (state & (1 << 8)) ? onpen : offpen);
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 8)) ? onpen : offpen);
// 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, (state & (1 << 9)) ? onpen : offpen);
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 9)) ? onpen : offpen);
// 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, (state & (1 << 10)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 10)) ? onpen : offpen);
// 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, (state & (1 << 11)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 11)) ? onpen : offpen);
// 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, (state & (1 << 12)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 12)) ? onpen : offpen);
// 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, (state & (1 << 13)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 13)) ? onpen : offpen);
// apply skew
apply_skew(tempbitmap, 40);
// comma tail
draw_segment_diagonal_1(tempbitmap,
- bmwidth - (segwidth/2), bmwidth + segwidth,
- bmheight - (segwidth), bmheight + segwidth*1.5,
- segwidth/2, (state & (1 << 15)) ? onpen : offpen);
+ bmwidth - (segwidth/2), bmwidth + segwidth,
+ bmheight - (segwidth), bmheight + segwidth*1.5,
+ segwidth/2, (state & (1 << 15)) ? onpen : offpen);
// decimal point
- draw_segment_decimal(tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (state & (1 << 14)) ? onpen : offpen);
+ draw_segment_decimal(tempbitmap,
+ bmwidth + segwidth/2, bmheight - segwidth/2,
+ segwidth, (state & (1 << 14)) ? onpen : offpen);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -2041,14 +2087,14 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- const rgb_t onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
- const rgb_t offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
+ rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff);
+ rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff);
// sizes for computation
- int bmwidth = 250;
- int bmheight = 400;
- int segwidth = 40;
- int skewwidth = 40;
+ int const bmwidth = 250;
+ int const bmheight = 400;
+ int const segwidth = 40;
+ int const skewwidth = 40;
// allocate a temporary bitmap for drawing
bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight + segwidth);
@@ -2056,102 +2102,103 @@ protected:
// top-left bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
- segwidth, LINE_CAP_START, (state & (1 << 0)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
+ segwidth, LINE_CAP_START, (state & (1 << 0)) ? onpen : offpen);
// top-right bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
- segwidth, LINE_CAP_END, (state & (1 << 1)) ? onpen : offpen);
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, LINE_CAP_END, (state & (1 << 1)) ? onpen : offpen);
// right-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 2)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 2)) ? onpen : offpen);
// right-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
- segwidth, (state & (1 << 3)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (state & (1 << 3)) ? onpen : offpen);
// bottom-right bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
- segwidth, LINE_CAP_END, (state & (1 << 4)) ? onpen : offpen);
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, LINE_CAP_END, (state & (1 << 4)) ? onpen : offpen);
// bottom-left bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
- segwidth, LINE_CAP_START, (state & (1 << 5)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
+ segwidth, LINE_CAP_START, (state & (1 << 5)) ? onpen : offpen);
// left-bottom bar
draw_segment_vertical(tempbitmap,
- bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 6)) ? onpen : offpen);
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 6)) ? onpen : offpen);
// left-top bar
draw_segment_vertical(tempbitmap,
- 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
- segwidth, (state & (1 << 7)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (state & (1 << 7)) ? onpen : offpen);
// horizontal-middle-left bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
- segwidth, LINE_CAP_START, (state & (1 << 8)) ? onpen : offpen);
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (state & (1 << 8)) ? onpen : offpen);
// horizontal-middle-right bar
draw_segment_horizontal_caps(tempbitmap,
- 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
- segwidth, LINE_CAP_END, (state & (1 << 9)) ? onpen : offpen);
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (state & (1 << 9)) ? onpen : offpen);
// 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, (state & (1 << 10)) ? onpen : offpen);
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 10)) ? onpen : offpen);
// 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, (state & (1 << 11)) ? onpen : offpen);
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (state & (1 << 11)) ? onpen : offpen);
// 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, (state & (1 << 12)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 12)) ? onpen : offpen);
// 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, (state & (1 << 13)) ? onpen : offpen);
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 13)) ? onpen : offpen);
// 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, (state & (1 << 14)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (state & (1 << 14)) ? onpen : offpen);
// 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, (state & (1 << 15)) ? onpen : offpen);
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (state & (1 << 15)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(tempbitmap, 40);
// comma tail
draw_segment_diagonal_1(tempbitmap,
- bmwidth - (segwidth/2), bmwidth + segwidth,
- bmheight - (segwidth), bmheight + segwidth*1.5,
- segwidth/2, (state & (1 << 17)) ? onpen : offpen);
+ bmwidth - (segwidth/2), bmwidth + segwidth, bmheight - (segwidth), bmheight + segwidth*1.5,
+ segwidth/2, (state & (1 << 17)) ? onpen : offpen);
// decimal point (draw last for priority)
- draw_segment_decimal(tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (state & (1 << 16)) ? onpen : offpen);
-
- // apply skew
- apply_skew(tempbitmap, 40);
+ draw_segment_decimal(tempbitmap,
+ bmwidth + segwidth/2, bmheight - segwidth/2,
+ segwidth, (state & (1 << 16)) ? onpen : offpen);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
};
@@ -2188,7 +2235,7 @@ protected:
draw_segment_decimal(tempbitmap, ((dotwidth / 2) + (i * dotwidth)), bmheight / 2, dotwidth, BIT(state, i) ? onpen : offpen);
// resample to the target size
- render_resample_argb_bitmap_hq(dest, tempbitmap, color());
+ render_resample_argb_bitmap_hq(dest, tempbitmap, color(state));
}
private:
@@ -2216,9 +2263,8 @@ protected:
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
{
- render_font *font = machine.render().font_alloc("default");
- std::string temp = string_format("%0*d", m_digits, state);
- draw_text(*font, dest, bounds, temp.c_str(), m_textalign);
+ render_font *const font = machine.render().font_alloc("default");
+ draw_text(*font, dest, bounds, string_format("%0*d", m_digits, state).c_str(), m_textalign, color(state));
machine.render().font_free(font);
}
@@ -2307,10 +2353,11 @@ protected:
int use_state = (state + m_stateoffset) % max_state_used;
// compute premultiplied colors
- u32 r = color().r * 255.0f;
- u32 g = color().g * 255.0f;
- u32 b = color().b * 255.0f;
- u32 a = color().a * 255.0f;
+ render_color const c(color(state));
+ u32 const r = c.r * 255.0f;
+ u32 const g = c.g * 255.0f;
+ u32 const b = c.b * 255.0f;
+ u32 const a = c.a * 255.0f;
// get the width of the string
render_font *font = machine.render().font_alloc("default");
@@ -2367,7 +2414,7 @@ protected:
if (m_bitmap[fruit].valid())
{
- render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], color());
+ render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
for (int y = 0; y < ourheight/num_shown; y++)
{
@@ -2468,10 +2515,11 @@ private:
int use_state = (state + m_stateoffset) % max_state_used;
// compute premultiplied colors
- u32 r = color().r * 255.0f;
- u32 g = color().g * 255.0f;
- u32 b = color().b * 255.0f;
- u32 a = color().a * 255.0f;
+ render_color const c(color(state));
+ u32 const r = c.r * 255.0f;
+ u32 const g = c.g * 255.0f;
+ u32 const b = c.b * 255.0f;
+ u32 const a = c.a * 255.0f;
// get the width of the string
render_font *font = machine.render().font_alloc("default");
@@ -2526,7 +2574,7 @@ private:
if (m_bitmap[fruit].valid())
{
- render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], color());
+ render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
for (int y = 0; y < dest.height(); y++)
{
@@ -2736,10 +2784,206 @@ layout_element::texture &layout_element::texture::operator=(texture &&that)
//-------------------------------------------------
layout_element::component::component(environment &env, util::xml::data_node const &compnode, const char *dirname)
- : m_state(env.get_attribute_int(compnode, "state", -1))
- , m_color(env.parse_color(compnode.get_child("color")))
+ : m_statemask(env.get_attribute_int(compnode, "statemask", env.get_attribute_string(compnode, "state", "")[0] ? ~0 : 0))
+ , m_stateval(env.get_attribute_int(compnode, "state", m_statemask) & m_statemask)
+{
+ for (util::xml::data_node const *child = compnode.get_first_child(); child; child = child->get_next_sibling())
+ {
+ if (!strcmp(child->get_name(), "bounds"))
+ {
+ int const state(env.get_attribute_int(*child, "state", 0));
+ auto const pos(
+ std::lower_bound(
+ m_bounds.begin(),
+ m_bounds.end(),
+ state,
+ [] (bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
+ if ((m_bounds.end() != pos) && (state == pos->state))
+ {
+ throw layout_syntax_error(
+ util::string_format(
+ "%s component has duplicate bounds for state %d",
+ compnode.get_name(),
+ state));
+ }
+ bounds_step &ins(*m_bounds.emplace(pos, bounds_step{ state, { 0.0F, 0.0F, 0.0F, 0.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } }));
+ env.parse_bounds(child, ins.bounds);
+ }
+ else if (!strcmp(child->get_name(), "color"))
+ {
+ int const state(env.get_attribute_int(*child, "state", 0));
+ auto const pos(
+ std::lower_bound(
+ m_color.begin(),
+ m_color.end(),
+ state,
+ [] (color_step const &lhs, int rhs) { return lhs.state < rhs; }));
+ if ((m_color.end() != pos) && (state == pos->state))
+ {
+ throw layout_syntax_error(
+ util::string_format(
+ "%s component has duplicate color for state %d",
+ compnode.get_name(),
+ state));
+ }
+ m_color.emplace(pos, color_step{ state, env.parse_color(child), { 0.0F, 0.0F, 0.0F, 0.0F } });
+ }
+ }
+ if (m_bounds.empty())
+ {
+ m_bounds.emplace_back(bounds_step{ 0, { 0.0F, 0.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
+ }
+ else
+ {
+ auto i(m_bounds.begin());
+ auto j(i);
+ while (m_bounds.end() != ++j)
+ {
+ assert(j->state > i->state);
+
+ i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
+ i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
+ i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
+ i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
+
+ i = j;
+ }
+ }
+ if (m_color.empty())
+ {
+ m_color.emplace_back(color_step{ 0, { 1.0F, 1.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
+ }
+ else
+ {
+ auto i(m_color.begin());
+ auto j(i);
+ while (m_color.end() != ++j)
+ {
+ assert(j->state > i->state);
+
+ i->delta.a = (j->color.a - i->color.a) / (j->state - i->state);
+ i->delta.r = (j->color.r - i->color.r) / (j->state - i->state);
+ i->delta.g = (j->color.g - i->color.g) / (j->state - i->state);
+ i->delta.b = (j->color.b - i->color.b) / (j->state - i->state);
+
+ i = j;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// statewrap - get state wraparound requirements
+//-------------------------------------------------
+
+std::pair<int, bool> layout_element::component::statewrap() const
+{
+ int result(0);
+ bool fold;
+ auto const adjustmask =
+ [&result, &fold] (int val, int mask)
+ {
+ assert(!(val & ~mask));
+ auto const splatright =
+ [] (int x)
+ {
+ for (unsigned shift = 1; (sizeof(x) * 4) >= shift; shift <<= 1)
+ x |= (x >> shift);
+ return x;
+ };
+ int const unfolded(splatright(mask));
+ int const folded(splatright(~mask | splatright(val)));
+ if (unsigned(folded) < unsigned(unfolded))
+ {
+ result |= folded;
+ fold = true;
+ }
+ else
+ {
+ result |= unfolded;
+ }
+ };
+ adjustmask(stateval(), statemask());
+ int max(maxstate());
+ if (m_bounds.size() > 1U)
+ max = (std::max)(max, m_bounds.back().state);
+ if (m_color.size() > 1U)
+ max = (std::max)(max, m_color.back().state);
+ if (0 <= max)
+ adjustmask(max, ~0);
+ return std::make_pair(result, fold);
+}
+
+
+//-------------------------------------------------
+// overall_bounds - maximum bounds for all states
+//-------------------------------------------------
+
+render_bounds layout_element::component::overall_bounds() const
{
- env.parse_bounds(compnode.get_child("bounds"), m_bounds);
+ auto i(m_bounds.begin());
+ render_bounds result(i->bounds);
+ while (m_bounds.end() != ++i)
+ union_render_bounds(result, i->bounds);
+ return result;
+}
+
+
+//-------------------------------------------------
+// bounds - bounds for a given state
+//-------------------------------------------------
+
+render_bounds layout_element::component::bounds(int state) const
+{
+ auto pos(
+ std::lower_bound(
+ m_bounds.begin(),
+ m_bounds.end(),
+ state,
+ [] (bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
+ if (m_bounds.begin() == pos)
+ {
+ return pos->bounds;
+ }
+ else
+ {
+ --pos;
+ render_bounds result(pos->bounds);
+ result.x0 += pos->delta.x0 * (state - pos->state);
+ result.x1 += pos->delta.x1 * (state - pos->state);
+ result.y0 += pos->delta.y0 * (state - pos->state);
+ result.y1 += pos->delta.y1 * (state - pos->state);
+ return result;
+ }
+}
+
+
+//-------------------------------------------------
+// color - color for a given state
+//-------------------------------------------------
+
+render_color layout_element::component::color(int state) const
+{
+ auto pos(
+ std::lower_bound(
+ m_color.begin(),
+ m_color.end(),
+ state,
+ [] (color_step const &lhs, int rhs) { return lhs.state < rhs; }));
+ if (m_color.begin() == pos)
+ {
+ return pos->color;
+ }
+ else
+ {
+ --pos;
+ render_color result(pos->color);
+ result.a += pos->delta.a * (state - pos->state);
+ result.r += pos->delta.r * (state - pos->state);
+ result.g += pos->delta.g * (state - pos->state);
+ result.b += pos->delta.b * (state - pos->state);
+ return result;
+ }
}
@@ -2749,10 +2993,27 @@ layout_element::component::component(environment &env, util::xml::data_node cons
void layout_element::component::normalize_bounds(float xoffs, float yoffs, float xscale, float yscale)
{
- m_bounds.x0 = (m_bounds.x0 - xoffs) * xscale;
- m_bounds.x1 = (m_bounds.x1 - xoffs) * xscale;
- m_bounds.y0 = (m_bounds.y0 - yoffs) * yscale;
- m_bounds.y1 = (m_bounds.y1 - yoffs) * yscale;
+ auto i(m_bounds.begin());
+ i->bounds.x0 = (i->bounds.x0 - xoffs) * xscale;
+ i->bounds.x1 = (i->bounds.x1 - xoffs) * xscale;
+ i->bounds.y0 = (i->bounds.y0 - yoffs) * yscale;
+ i->bounds.y1 = (i->bounds.y1 - yoffs) * yscale;
+
+ auto j(i);
+ while (m_bounds.end() != ++j)
+ {
+ j->bounds.x0 = (j->bounds.x0 - xoffs) * xscale;
+ j->bounds.x1 = (j->bounds.x1 - xoffs) * xscale;
+ j->bounds.y0 = (j->bounds.y0 - yoffs) * yscale;
+ j->bounds.y1 = (j->bounds.y1 - yoffs) * yscale;
+
+ i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
+ i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
+ i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
+ i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
+
+ i = j;
+ }
}
@@ -2760,13 +3021,19 @@ void layout_element::component::normalize_bounds(float xoffs, float yoffs, float
// draw_text - draw text in the specified color
//-------------------------------------------------
-void layout_element::component::draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, const char *str, int align)
+void layout_element::component::draw_text(
+ render_font &font,
+ bitmap_argb32 &dest,
+ const rectangle &bounds,
+ const char *str,
+ int align,
+ const render_color &color)
{
// compute premultiplied colors
- u32 r = color().r * 255.0f;
- u32 g = color().g * 255.0f;
- u32 b = color().b * 255.0f;
- u32 a = color().a * 255.0f;
+ u32 const r(color.r * 255.0f);
+ u32 const g(color.g * 255.0f);
+ u32 const b(color.b * 255.0f);
+ u32 const a(color.a * 255.0f);
// get the width of the string
float aspect = 1.0f;