diff options
Diffstat (limited to 'src/emu/rendlay.cpp')
-rw-r--r-- | src/emu/rendlay.cpp | 417 |
1 files changed, 253 insertions, 164 deletions
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index 2c4057501d6..b47d643e254 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -20,6 +20,7 @@ #include <ctype.h> #include <algorithm> +#include <cmath> #include <cstddef> #include <cstdio> #include <cstring> @@ -69,23 +70,26 @@ enum std::locale const f_portable_locale("C"); +constexpr layout_group::transform identity_transform{{ {{ 1.0F, 0.0F, 0.0F }}, {{ 0.0F, 1.0F, 0.0F }}, {{ 0.0F, 0.0F, 1.0F }} }}; + //************************************************************************** // INLINE HELPERS //************************************************************************** -//------------------------------------------------- -// render_bounds_transform - apply translation/ -// scaling -//------------------------------------------------- +inline void render_bounds_transform(render_bounds &bounds, layout_group::transform const &trans) +{ + bounds = render_bounds{ + (bounds.x0 * trans[0][0]) + (bounds.y0 * trans[0][1]) + trans[0][2], + (bounds.x0 * trans[1][0]) + (bounds.y0 * trans[1][1]) + trans[1][2], + (bounds.x1 * trans[0][0]) + (bounds.y1 * trans[0][1]) + trans[0][2], + (bounds.x1 * trans[1][0]) + (bounds.y1 * trans[1][1]) + trans[1][2] }; +} -inline void render_bounds_transform(render_bounds &bounds, render_bounds const &transform) +constexpr render_color render_color_multiply(render_color const &x, render_color const &y) { - bounds.x0 = (bounds.x0 * transform.x1) + transform.x0; - bounds.y0 = (bounds.y0 * transform.y1) + transform.y0; - bounds.x1 = (bounds.x1 * transform.x1) + transform.x0; - bounds.y1 = (bounds.y1 * transform.y1) + transform.y0; + return render_color{ x.a * y.a, x.r * y.r, x.g * y.g, x.b * y.b }; } @@ -129,7 +133,7 @@ private: , m_int_increment(i) , m_shift(s) , m_text_valid(true) - , m_incrementing(true) + , m_generator(true) { } entry(std::string &&name, std::string &&t, double i, int s) : m_name(std::move(name)) @@ -137,7 +141,7 @@ private: , m_float_increment(i) , m_shift(s) , m_text_valid(true) - , m_incrementing(true) + , m_generator(true) { } entry(entry &&) = default; entry &operator=(entry &&) = default; @@ -165,7 +169,7 @@ private: } std::string const &name() const { return m_name; } - bool is_incrementing() const { return m_incrementing; } + bool is_generator() const { return m_generator; } std::string const &get_text() { @@ -187,7 +191,7 @@ private: void increment() { - if (is_incrementing()) + if (is_generator()) { // apply increment if (m_float_increment) @@ -342,7 +346,7 @@ private: bool m_text_valid = false; bool m_int_valid = false; bool m_float_valid = false; - bool m_incrementing = false; + bool m_generator = false; }; using entry_vector = std::vector<entry>; @@ -631,7 +635,7 @@ public: throw layout_syntax_error("increment attribute must be a number"); } - // don't allow incrementing parameters to be redefined + // don't allow generator parameters to be redefined if (init) { entry_vector::iterator const pos( @@ -641,7 +645,7 @@ public: name, [] (entry const &lhs, auto const &rhs) { return lhs.name() < rhs; })); if ((m_entries.end() != pos) && (pos->name() == name)) - throw layout_syntax_error("incrementing parameters must be defined exactly once per scope"); + throw layout_syntax_error("generator parameters must be defined exactly once per scope"); std::pair<char const *, char const *> const expanded(expand(start)); if (floatincrement) @@ -668,8 +672,8 @@ public: [] (entry const &lhs, auto const &rhs) { return lhs.name() < rhs; })); if ((m_entries.end() == pos) || (pos->name() != name)) m_entries.emplace(pos, std::move(name), std::string(expanded.first, expanded.second)); - else if (pos->is_incrementing()) - throw layout_syntax_error("incrementing parameters must be defined exactly once per scope"); + else if (pos->is_generator()) + throw layout_syntax_error("generator parameters must be defined exactly once per scope"); else pos->set(std::string(expanded.first, expanded.second)); } @@ -677,8 +681,18 @@ public: void increment_parameters() { - for (entry &e : m_entries) - e.increment(); + m_entries.erase( + std::remove_if( + m_entries.begin(), + m_entries.end(), + [] (entry &e) + { + if (!e.is_generator()) + return true; + e.increment(); + return false; + }), + m_entries.end()); } char const *get_attribute_string(util::xml::data_node const &node, char const *name, char const *defvalue) @@ -778,53 +792,50 @@ public: } } - void parse_color(util::xml::data_node const *node, render_color &result) + render_color parse_color(util::xml::data_node const *node) { - // default to white + // default to opaque white if (!node) - { - result.r = result.g = result.b = result.a = 1.0F; - } - else - { - // parse attributes - result.r = get_attribute_float(*node, "red", 1.0F); - result.g = get_attribute_float(*node, "green", 1.0F); - result.b = get_attribute_float(*node, "blue", 1.0F); - result.a = get_attribute_float(*node, "alpha", 1.0F); + return render_color{ 1.0F, 1.0F, 1.0F, 1.0F }; - // check for errors - if ((0.0F > (std::min)({ result.r, result.g, result.b, result.a })) || (1.0F < (std::max)({ result.r, result.g, result.b, result.a }))) - throw layout_syntax_error(util::string_format("illegal RGBA color %f,%f,%f,%f", result.r, result.g, result.b, result.a)); - } + // parse attributes + render_color const result{ + get_attribute_float(*node, "alpha", 1.0F), + get_attribute_float(*node, "red", 1.0F), + get_attribute_float(*node, "green", 1.0F), + get_attribute_float(*node, "blue", 1.0F) }; + + // check for errors + if ((0.0F > (std::min)({ result.r, result.g, result.b, result.a })) || (1.0F < (std::max)({ result.r, result.g, result.b, result.a }))) + throw layout_syntax_error(util::string_format("illegal RGBA color %f,%f,%f,%f", result.r, result.g, result.b, result.a)); + + return result; } - void parse_orientation(util::xml::data_node const *node, int &result) + int parse_orientation(util::xml::data_node const *node) { // default to no transform if (!node) - { - result = ROT0; - } - else - { - // parse attributes - int const rotate(get_attribute_int(*node, "rotate", 0)); - switch (rotate) - { - case 0: result = ROT0; break; - case 90: result = ROT90; break; - case 180: result = ROT180; break; - case 270: result = ROT270; break; - default: throw layout_syntax_error(util::string_format("invalid rotate attribute %d", rotate)); - } - if (!std::strcmp("yes", get_attribute_string(*node, "swapxy", "no"))) - result ^= ORIENTATION_SWAP_XY; - if (!std::strcmp("yes", get_attribute_string(*node, "flipx", "no"))) - result ^= ORIENTATION_FLIP_X; - if (!std::strcmp("yes", get_attribute_string(*node, "flipy", "no"))) - result ^= ORIENTATION_FLIP_Y; - } + return ROT0; + + // parse attributes + int result; + int const rotate(get_attribute_int(*node, "rotate", 0)); + switch (rotate) + { + case 0: result = ROT0; break; + case 90: result = ROT90; break; + case 180: result = ROT180; break; + case 270: result = ROT270; break; + default: throw layout_syntax_error(util::string_format("invalid rotate attribute %d", rotate)); + } + if (!std::strcmp("yes", get_attribute_string(*node, "swapxy", "no"))) + result ^= ORIENTATION_SWAP_XY; + if (!std::strcmp("yes", get_attribute_string(*node, "flipx", "no"))) + result ^= ORIENTATION_FLIP_X; + if (!std::strcmp("yes", get_attribute_string(*node, "flipy", "no"))) + result ^= ORIENTATION_FLIP_Y; + return result; } }; @@ -955,25 +966,65 @@ layout_group::~layout_group() // matrix for given destination bounds //------------------------------------------------- -render_bounds layout_group::make_transform(render_bounds const &dest) const +layout_group::transform layout_group::make_transform(int orientation, render_bounds const &dest) const +{ + assert(m_bounds_resolved); + + // make orientation matrix + transform result{{ {{ 1.0F, 0.0F, 0.0F }}, {{ 0.0F, 1.0F, 0.0F }}, {{ 0.0F, 0.0F, 1.0F }} }}; + if (orientation & ORIENTATION_SWAP_XY) + { + std::swap(result[0][0], result[0][1]); + std::swap(result[1][0], result[1][1]); + } + if (orientation & ORIENTATION_FLIP_X) + { + result[0][0] = -result[0][0]; + result[0][1] = -result[0][1]; + } + if (orientation & ORIENTATION_FLIP_Y) + { + result[1][0] = -result[1][0]; + result[1][1] = -result[1][1]; + } + + // apply to bounds and force into destination rectangle + render_bounds bounds(m_bounds); + render_bounds_transform(bounds, result); + result[0][0] *= (dest.x1 - dest.x0) / std::fabs(bounds.x1 - bounds.x0); + result[0][1] *= (dest.x1 - dest.x0) / std::fabs(bounds.x1 - bounds.x0); + result[0][2] = dest.x0 - ((std::min)(bounds.x0, bounds.x1) * (dest.x1 - dest.x0) / std::fabs(bounds.x1 - bounds.x0)); + result[1][0] *= (dest.y1 - dest.y0) / std::fabs(bounds.y1 - bounds.y0); + result[1][1] *= (dest.y1 - dest.y0) / std::fabs(bounds.y1 - bounds.y0); + result[1][2] = dest.y0 - ((std::min)(bounds.y0, bounds.y1) * (dest.y1 - dest.y0) / std::fabs(bounds.y1 - bounds.y0)); + return result; +} + +layout_group::transform layout_group::make_transform(int orientation, transform const &trans) const { assert(m_bounds_resolved); - return render_bounds{ - dest.x0 - (m_bounds.x0 * (dest.x1 - dest.x0) / (m_bounds.x1 - m_bounds.x0)), - dest.y0 - (m_bounds.y0 * (dest.y1 - dest.y0) / (m_bounds.y1 - m_bounds.y0)), - (dest.x1 - dest.x0) / (m_bounds.x1 - m_bounds.x0), - (dest.y1 - dest.y0) / (m_bounds.y1 - m_bounds.y0) }; + render_bounds const dest{ + m_bounds.x0, + m_bounds.y0, + (orientation & ORIENTATION_SWAP_XY) ? (m_bounds.x0 + m_bounds.y1 - m_bounds.y0) : m_bounds.x1, + (orientation & ORIENTATION_SWAP_XY) ? (m_bounds.y0 + m_bounds.x1 - m_bounds.x0) : m_bounds.y1 }; + return make_transform(orientation, dest, trans); } -render_bounds layout_group::make_transform(render_bounds const &dest, render_bounds const &transform) const +layout_group::transform layout_group::make_transform(int orientation, render_bounds const &dest, transform const &trans) const { - render_bounds const next(make_transform(dest)); - return render_bounds{ - (transform.x0 * next.x1) + next.x0, - (transform.y0 * next.y1) + next.y0, - transform.x1 * next.x1, - transform.y1 * next.y1 }; + transform const next(make_transform(orientation, dest)); + transform result{{ {{ 0.0F, 0.0F, 0.0F }}, {{ 0.0F, 0.0F, 0.0F }}, {{ 0.0F, 0.0F, 0.0F }} }}; + for (unsigned y = 0; 3U > y; ++y) + { + for (unsigned x = 0; 3U > x; ++x) + { + for (unsigned i = 0; 3U > i; ++i) + result[y][x] += trans[y][i] * next[i][x]; + } + } + return result; } @@ -1003,8 +1054,8 @@ void layout_group::resolve_bounds(environment &env, group_map &groupmap, std::ve // a wild loop appears! std::ostringstream path; for (layout_group const *const group : seen) - path << ' ' << group->m_groupnode.get_name(); - path << ' ' << m_groupnode.get_name(); + path << ' ' << group->m_groupnode.get_attribute_string("name", nullptr); + path << ' ' << m_groupnode.get_attribute_string("name", nullptr); throw layout_syntax_error(util::string_format("recursively nested groups %s", path.str())); } @@ -1014,6 +1065,7 @@ void layout_group::resolve_bounds(environment &env, group_map &groupmap, std::ve environment local(env); resolve_bounds(local, m_groupnode, groupmap, seen, false, true); } + seen.pop_back(); } void layout_group::resolve_bounds( @@ -1061,17 +1113,33 @@ void layout_group::resolve_bounds( } else if (!strcmp(itemnode->get_name(), "group")) { - char const *ref(env.get_attribute_string(*itemnode, "ref", nullptr)); - if (!ref) - throw layout_syntax_error("nested group must have ref attribute"); - - group_map::iterator const found(groupmap.find(ref)); - if (groupmap.end() == found) - throw layout_syntax_error(util::string_format("unable to find group %s", ref)); - - environment local(env); - found->second.resolve_bounds(local, groupmap, seen); - union_render_bounds(m_bounds, found->second.m_bounds); + util::xml::data_node const *const itemboundsnode(itemnode->get_child("bounds")); + if (itemboundsnode) + { + render_bounds itembounds; + env.parse_bounds(itemboundsnode, itembounds); + union_render_bounds(m_bounds, itembounds); + } + else + { + char const *ref(env.get_attribute_string(*itemnode, "ref", nullptr)); + if (!ref) + throw layout_syntax_error("nested group must have ref attribute"); + + group_map::iterator const found(groupmap.find(ref)); + if (groupmap.end() == found) + throw layout_syntax_error(util::string_format("unable to find group %s", ref)); + + int const orientation(env.parse_orientation(itemnode->get_child("orientation"))); + environment local(env); + found->second.resolve_bounds(local, groupmap, seen); + render_bounds const itembounds{ + found->second.m_bounds.x0, + found->second.m_bounds.y0, + (orientation & ORIENTATION_SWAP_XY) ? (found->second.m_bounds.x0 + found->second.m_bounds.y1 - found->second.m_bounds.y0) : found->second.m_bounds.x1, + (orientation & ORIENTATION_SWAP_XY) ? (found->second.m_bounds.y0 + found->second.m_bounds.x1 - found->second.m_bounds.x0) : found->second.m_bounds.y1 }; + union_render_bounds(m_bounds, itembounds); + } } else if (!strcmp(itemnode->get_name(), "repeat")) { @@ -1139,11 +1207,11 @@ void layout_element::element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, c if (curcomp->state() == -1 || curcomp->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()); + 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())); bounds &= dest.cliprect(); // based on the component type, add to the texture @@ -1188,24 +1256,24 @@ private: ru_imgformat const format = render_detect_image(*m_file, m_dirname.c_str(), m_imagefile.c_str()); switch (format) { - case RENDUTIL_IMGFORMAT_ERROR: - break; - - 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()); + case RENDUTIL_IMGFORMAT_ERROR: + 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); - break; + 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()); + break; - default: - // try JPG - render_load_jpeg(m_bitmap, *m_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()); + 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); + // if we can't load the bitmap, allocate a dummy one and report an error if (!m_bitmap.valid()) { @@ -1255,9 +1323,9 @@ protected: u32 const inva = (1.0f - color().a) * 255.0f; // iterate over X and Y - for (u32 y = bounds.min_y; y <= bounds.max_y; y++) + for (u32 y = bounds.top(); y <= bounds.bottom(); y++) { - for (u32 x = bounds.min_x; x <= bounds.max_x; x++) + for (u32 x = bounds.left(); x <= bounds.right(); x++) { u32 finalr = r; u32 finalg = g; @@ -1308,7 +1376,7 @@ protected: float const ooyradius2 = 1.0f / (yradius * yradius); // iterate over y - for (u32 y = bounds.min_y; y <= bounds.max_y; y++) + for (u32 y = bounds.top(); y <= bounds.bottom(); y++) { float ycoord = ycenter - ((float)y + 0.5f); float xval = xradius * sqrtf(1.0f - (ycoord * ycoord) * ooyradius2); @@ -1399,31 +1467,31 @@ protected: tempbitmap.fill(rgb_t(0xff,0x00,0x00,0x00)); // top bar - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 0)) ? onpen : offpen); + draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2, segwidth, BIT(state, 0) ? onpen : offpen); // top-right bar - draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2, segwidth, (state & (1 << 1)) ? onpen : offpen); + draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2, segwidth, BIT(state, 1) ? onpen : offpen); // bottom-right bar - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2, segwidth, (state & (1 << 2)) ? onpen : offpen); + draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2, segwidth, BIT(state, 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); + draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2, segwidth, BIT(state, 3) ? onpen : offpen); // bottom-left bar - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 4)) ? onpen : offpen); + draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2, segwidth, BIT(state, 4) ? onpen : offpen); // top-left bar - draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 5)) ? onpen : offpen); + draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2, segwidth, BIT(state, 5) ? onpen : offpen); // middle bar - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight/2, segwidth, (state & (1 << 6)) ? onpen : offpen); + draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight/2, segwidth, BIT(state, 6) ? onpen : offpen); // apply skew apply_skew(tempbitmap, 40); // decimal point - draw_segment_decimal(tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (state & (1 << 7)) ? onpen : offpen); + 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()); @@ -2014,7 +2082,7 @@ protected: tempbitmap.fill(rgb_t(0xff, 0x00, 0x00, 0x00)); for (int i = 0; i < m_dots; i++) - draw_segment_decimal(tempbitmap, ((dotwidth/2 )+ (i * dotwidth)), bmheight/2, dotwidth, (state & (1 << i))?onpen:offpen); + 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()); @@ -2155,25 +2223,25 @@ protected: { int basey; - if (m_reelreversed==1) + if (m_reelreversed) { - basey = bounds.min_y + ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; + basey = bounds.top() + ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; } else { - basey = bounds.min_y - ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; + basey = bounds.top() - ((use_state)*(ourheight/num_shown)/(max_state_used/m_numstops)) + curry; } // wrap around... - if (basey < bounds.min_y) + if (basey < bounds.top()) basey += ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); - if (basey > bounds.max_y) + if (basey > bounds.bottom()) basey -= ((max_state_used)*(ourheight/num_shown)/(max_state_used/m_numstops)); int endpos = basey+ourheight/num_shown; // only render the symbol / text if it's atually in view because the code is SLOW - if ((endpos >= bounds.min_y) && (basey <= bounds.max_y)) + if ((endpos >= bounds.top()) && (basey <= bounds.bottom())) { while (1) { @@ -2184,7 +2252,7 @@ protected: } s32 curx; - curx = bounds.min_x + (bounds.width() - width) / 2; + curx = bounds.left() + (bounds.width() - width) / 2; if (m_file[fruit]) if (!m_bitmap[fruit].valid()) @@ -2202,14 +2270,14 @@ protected: { int effy = basey + y; - if (effy >= bounds.min_y && effy <= bounds.max_y) + if (effy >= bounds.top() && effy <= bounds.bottom()) { u32 *src = &tempbitmap2.pix32(y); u32 *d = &dest.pix32(effy); for (int x = 0; x < dest.width(); x++) { int effx = x; - if (effx >= bounds.min_x && effx <= bounds.max_x) + if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) @@ -2249,14 +2317,14 @@ protected: { int effy = basey + y; - if (effy >= bounds.min_y && effy <= bounds.max_y) + if (effy >= bounds.top() && effy <= bounds.bottom()) { u32 *src = &tempbitmap.pix32(y); u32 *d = &dest.pix32(effy); for (int x = 0; x < chbounds.width(); x++) { - int effx = curx + x + chbounds.min_x; - if (effx >= bounds.min_x && effx <= bounds.max_x) + int effx = curx + x + chbounds.left(); + if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) @@ -2324,15 +2392,15 @@ private: } // wrap around... - if (basex < bounds.min_x) + if (basex < bounds.left()) basex += ((max_state_used)*(ourwidth/num_shown)/(max_state_used/m_numstops)); - if (basex > bounds.max_x) + if (basex > bounds.right()) basex -= ((max_state_used)*(ourwidth/num_shown)/(max_state_used/m_numstops)); int endpos = basex+(ourwidth/num_shown); // only render the symbol / text if it's atually in view because the code is SLOW - if ((endpos >= bounds.min_x) && (basex <= bounds.max_x)) + if ((endpos >= bounds.left()) && (basex <= bounds.right())) { while (1) { @@ -2343,7 +2411,7 @@ private: } s32 curx; - curx = bounds.min_x; + curx = bounds.left(); if (m_file[fruit]) if (!m_bitmap[fruit].valid()) @@ -2361,14 +2429,14 @@ private: { int effy = y; - if (effy >= bounds.min_y && effy <= bounds.max_y) + if (effy >= bounds.top() && effy <= bounds.bottom()) { u32 *src = &tempbitmap2.pix32(y); u32 *d = &dest.pix32(effy); for (int x = 0; x < ourwidth/num_shown; x++) { int effx = basex + x; - if (effx >= bounds.min_x && effx <= bounds.max_x) + if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) @@ -2410,14 +2478,14 @@ private: { int effy = y; - if (effy >= bounds.min_y && effy <= bounds.max_y) + if (effy >= bounds.top() && effy <= bounds.bottom()) { u32 *src = &tempbitmap.pix32(y); u32 *d = &dest.pix32(effy); for (int x = 0; x < chbounds.width(); x++) { int effx = basex + curx + x; - if (effx >= bounds.min_x && effx <= bounds.max_x) + if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) @@ -2566,12 +2634,10 @@ 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(0) + : m_state(env.get_attribute_int(compnode, "state", -1)) + , m_color(env.parse_color(compnode.get_child("color"))) { - // fetch common data - m_state = env.get_attribute_int(compnode, "state", -1); env.parse_bounds(compnode.get_child("bounds"), m_bounds); - env.parse_color(compnode.get_child("color"), m_color); } @@ -2618,17 +2684,17 @@ void layout_element::component::draw_text(render_font &font, bitmap_argb32 &dest { // left case 1: - curx = bounds.min_x; + curx = bounds.left(); break; // right case 2: - curx = bounds.max_x - width; + curx = bounds.right() - width; break; // default to center default: - curx = bounds.min_x + (bounds.width() - width) / 2; + curx = bounds.left() + (bounds.width() - width) / 2; break; } @@ -2656,15 +2722,15 @@ void layout_element::component::draw_text(render_font &font, bitmap_argb32 &dest // copy the data into the target for (int y = 0; y < chbounds.height(); y++) { - int effy = bounds.min_y + y; - if (effy >= bounds.min_y && effy <= bounds.max_y) + int effy = bounds.top() + y; + if (effy >= bounds.top() && effy <= bounds.bottom()) { u32 *src = &tempbitmap.pix32(y); u32 *d = &dest.pix32(effy); for (int x = 0; x < chbounds.width(); x++) { - int effx = curx + x + chbounds.min_x; - if (effx >= bounds.min_x && effx <= bounds.max_x) + int effx = curx + x + chbounds.left(); + if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) @@ -2894,7 +2960,7 @@ layout_view::layout_view( m_expbounds.x0 = m_expbounds.y0 = m_expbounds.x1 = m_expbounds.y1 = 0; environment local(env); local.set_parameter("viewname", std::string(m_name)); - add_items(local, viewnode, elemmap, groupmap, render_bounds{ 0.0f, 0.0f, 1.0f, 1.0f }, true, false, true); + add_items(local, viewnode, elemmap, groupmap, ROT0, identity_transform, render_color{ 1.0F, 1.0F, 1.0F, 1.0F }, true, false, true); recompute(render_layer_config()); for (group_map::value_type &group : groupmap) group.second.set_bounds_unresolved(); @@ -3055,7 +3121,9 @@ void layout_view::add_items( util::xml::data_node const &parentnode, element_map &elemmap, group_map &groupmap, - render_bounds const &transform, + int orientation, + layout_group::transform const &trans, + render_color const &color, bool root, bool repeat, bool init) @@ -3086,27 +3154,27 @@ void layout_view::add_items( } else if (!strcmp(itemnode->get_name(), "backdrop")) { - m_backdrop_list.emplace_back(env, *itemnode, elemmap, transform); + m_backdrop_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "screen")) { - m_screen_list.emplace_back(env, *itemnode, elemmap, transform); + m_screen_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "overlay")) { - m_overlay_list.emplace_back(env, *itemnode, elemmap, transform); + m_overlay_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "bezel")) { - m_bezel_list.emplace_back(env, *itemnode, elemmap, transform); + m_bezel_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "cpanel")) { - m_cpanel_list.emplace_back(env, *itemnode, elemmap, transform); + m_cpanel_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "marquee")) { - m_marquee_list.emplace_back(env, *itemnode, elemmap, transform); + m_marquee_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); } else if (!strcmp(itemnode->get_name(), "group")) { @@ -3120,17 +3188,33 @@ void layout_view::add_items( unresolved = false; found->second.resolve_bounds(env, groupmap); - render_bounds grouptrans(transform); + layout_group::transform grouptrans(trans); util::xml::data_node const *const itemboundsnode(itemnode->get_child("bounds")); + util::xml::data_node const *const itemorientnode(itemnode->get_child("orientation")); + int const grouporient(env.parse_orientation(itemorientnode)); if (itemboundsnode) { render_bounds itembounds; env.parse_bounds(itemboundsnode, itembounds); - grouptrans = found->second.make_transform(itembounds, transform); + grouptrans = found->second.make_transform(grouporient, itembounds, trans); + } + else if (itemorientnode) + { + grouptrans = found->second.make_transform(grouporient, trans); } environment local(env); - add_items(local, found->second.get_groupnode(), elemmap, groupmap, grouptrans, false, false, true); + add_items( + local, + found->second.get_groupnode(), + elemmap, + groupmap, + orientation_add(grouporient, orientation), + grouptrans, + render_color_multiply(env.parse_color(itemnode->get_child("color")), color), + false, + false, + true); } else if (!strcmp(itemnode->get_name(), "repeat")) { @@ -3140,7 +3224,7 @@ void layout_view::add_items( environment local(env); for (int i = 0; count > i; ++i) { - add_items(local, *itemnode, elemmap, groupmap, transform, false, true, !i); + add_items(local, *itemnode, elemmap, groupmap, orientation, trans, color, false, true, !i); local.increment_parameters(); } } @@ -3190,7 +3274,9 @@ layout_view::item::item( environment &env, util::xml::data_node const &itemnode, element_map &elemmap, - render_bounds const &transform) + int orientation, + layout_group::transform const &trans, + render_color const &color) : m_element(nullptr) , m_output(env.device(), env.get_attribute_string(itemnode, "name", "")) , m_have_output(env.get_attribute_string(itemnode, "name", "")[0]) @@ -3198,7 +3284,8 @@ layout_view::item::item( , m_input_port(nullptr) , m_input_mask(0) , m_screen(nullptr) - , m_orientation(ROT0) + , m_orientation(orientation_add(env.parse_orientation(itemnode.get_child("orientation")), orientation)) + , m_color(render_color_multiply(env.parse_color(itemnode.get_child("color")), color)) { // find the associated element char const *const name(env.get_attribute_string(itemnode, "element", nullptr)); @@ -3224,9 +3311,11 @@ layout_view::item::item( if (m_have_output && m_element) m_output = m_element->default_state(); env.parse_bounds(itemnode.get_child("bounds"), m_rawbounds); - render_bounds_transform(m_rawbounds, transform); - env.parse_color(itemnode.get_child("color"), m_color); - env.parse_orientation(itemnode.get_child("orientation"), m_orientation); + render_bounds_transform(m_rawbounds, trans); + if (m_rawbounds.x0 > m_rawbounds.x1) + std::swap(m_rawbounds.x0, m_rawbounds.x1); + if (m_rawbounds.y0 > m_rawbounds.y1) + std::swap(m_rawbounds.y0, m_rawbounds.y1); // sanity checks if (strcmp(itemnode.get_name(), "screen") == 0) |