text:
/*
    Copyright 2013 Adobe
    Distributed under the Boost Software License, Version 1.0.
    (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/**************************************************************************************************/

#include <adobe/eve.hpp>

#include <iterator>
#include <utility>

#include <boost/bind/bind.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant/static_visitor.hpp>

#include <adobe/algorithm/for_each.hpp>
#include <adobe/algorithm/for_each_position.hpp>
#include <adobe/algorithm/transform.hpp>
#include <adobe/cmath.hpp>
#include <adobe/forest.hpp>
#include <adobe/functional.hpp>
#include <adobe/iterator.hpp>
#include <adobe/numeric.hpp>

#ifndef NDEBUG
#include <iostream>
#endif

/**************************************************************************************************/

using namespace boost::placeholders;

/**************************************************************************************************/

namespace {

using adobe::eve_t;

struct filter_visible {
    bool operator()(const adobe::implementation::view_proxy_t& x);
};

typedef adobe::filter_fullorder_iterator<adobe::eve_t::proxy_tree_t::iterator, filter_visible>
    cursor;
typedef boost::filter_iterator<filter_visible, adobe::child_iterator<cursor>> child_iterator;
typedef std::reverse_iterator<child_iterator> reverse_child_iterator;

inline child_iterator child_begin(cursor c) {
    return child_iterator(filter_visible(), adobe::child_begin(c), adobe::child_end(c));
}

inline child_iterator child_end(cursor c) {
    return child_iterator(filter_visible(), adobe::child_end(c), adobe::child_end(c));
}

/**************************************************************************************************/

} // namespace

/**************************************************************************************************/

#ifdef ADOBE_HAS_CPLUS0X_CONCEPTS
#include <concepts>
namespace std {
concept_map
    RandomAccessIterator<boost::filter_iterator<filter_visible, adobe::child_iterator<cursor>>>{};
}
#endif

/*
    REVISIT (sparent) : namespace adobe::implementation used instead of unnamed to support friend
    in eve_t.
*/

namespace adobe {
namespace implementation {

/**************************************************************************************************/

struct view_proxy_t : adobe::extents_slices_t {
    view_proxy_t(const layout_attributes_t&, poly_placeable_t&);

    poly_placeable_t& placeable_m;

    bool visible_m;

    typedef boost::array<guide_set_t, 2> fr_guide_set_t;

    layout_attributes_t geometry_m; // REVISIT (sparent) : make const
    place_data_t place_m;

    int space_before_m;                      // populated from spacing_m of parent
    boost::array<int, 2> container_length_m; // calculated length of container
    boost::array<int, 2> measured_length_m;  // length of container children only

    boost::array<fr_guide_set_t, 2> container_guide_set_m; // forward/reverse guide set for
    // container

    void calculate();
    void calculate_vertical();
    void place();

    void adjust(::child_iterator, ::child_iterator, slice_select_t);
    void solve_up(::child_iterator, ::child_iterator, slice_select_t slice);
    bool solve_down(::child_iterator, ::child_iterator, slice_select_t slice);
    void layout(::child_iterator, ::child_iterator, slice_select_t slice);
    void flatten(::child_iterator, ::child_iterator, slice_select_t slice,
                 adobe::eve_t::evaluate_options_t);

    void adjust_outsets(::child_iterator, ::child_iterator, slice_select_t);
    void adjust_outsets_with(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void adjust_outsets_cross(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void adjust_with(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void adjust_cross(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void solve_up_with(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void solve_up_cross(::child_iterator first, ::child_iterator last, slice_select_t slice);
    bool solve_down_with(::child_iterator first, ::child_iterator last, slice_select_t slice);
    bool solve_down_cross(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void layout_with(::child_iterator first, ::child_iterator last, slice_select_t slice);
    void layout_cross(::child_iterator first, ::child_iterator last, slice_select_t slice);
};

/**************************************************************************************************/

} // namespace implementation
} // namespace adobe

/**************************************************************************************************/
#if !defined(ADOBE_NO_DOCUMENTATION)
namespace {

inline bool filter_visible::operator()(const adobe::implementation::view_proxy_t& x) {
    return x.visible_m;
}

/**************************************************************************************************/

typedef adobe::implementation::view_proxy_t::slice_select_t slice_select_t;
typedef void (adobe::implementation::view_proxy_t::*apply_member_t)(::child_iterator,
                                                                    ::child_iterator,
                                                                    ::slice_select_t);

/*
    REVISIT (sparent) : VC 7.1 cannot handle the apply_member_t as a template parameter.
    Unfortunate, as this form would be more efficient.
*/
#if 0
template<typename BeadIterator, ::apply_member_t Apply>
struct apply_to_children
{
    typedef void result_type;

    explicit apply_to_children(::slice_select_t select) : select_m(select) { }

    void operator()(BeadIterator iter)const
    {
        ((*iter).*Apply)(::child_begin(iter.base()), ::child_end(iter.base()), select_m);
    }

private:
    ::slice_select_t select_m;
};
#endif
#if 1
template <typename BeadIterator>
struct apply_to_children {
    typedef void result_type;
    explicit apply_to_children(::apply_member_t apply, ::slice_select_t select)
        : apply_m(apply), select_m(select) {}

    void operator()(BeadIterator iter) {
        ((*iter).*apply_m)(::child_begin(iter.base()), ::child_end(iter.base()), select_m);
    }

private:
    ::apply_member_t apply_m;
    ::slice_select_t select_m;
};
#endif

/*
    REVISIT (sparent) : This is a quick fix for flatten - I think we could do much of what is
    here more efficiently.
*/

struct apply_flatten_t {
    typedef void result_type;

    explicit apply_flatten_t(slice_select_t select, adobe::eve_t::evaluate_options_t options)
        : options_m(options), select_m(select) {}

    template <typename BeadIterator>
    void operator()(BeadIterator iter) {
        iter->flatten(::child_begin(iter.base()), ::child_end(iter.base()), select_m, options_m);
    }

private:
    adobe::eve_t::evaluate_options_t options_m;
    slice_select_t select_m;
};

/**************************************************************************************************/

bool is_with(adobe::eve_t::placement_t placement, adobe::eve_t::slice_select_t select) {
    return ((placement == adobe::eve_t::place_column) && (select == adobe::eve_t::vertical)) ||
           ((placement == adobe::eve_t::place_row) && (select == adobe::eve_t::horizontal));
}

/**************************************************************************************************/

} // namespace
#endif
/**************************************************************************************************/

#if 0
#pragma mark -
#endif

/**************************************************************************************************/

namespace adobe {

/**************************************************************************************************/

void set_margin(layout_attributes_t& container, int x) {
    container.slice_m[eve_t::horizontal].margin_m.first = x;
    container.slice_m[eve_t::horizontal].margin_m.second = x;
    container.slice_m[eve_t::vertical].margin_m.first = x;
    container.slice_m[eve_t::vertical].margin_m.second = x;
}

/**************************************************************************************************/

#if 0
#pragma mark -
#endif

/**************************************************************************************************/

class eve_t::implementation_t : private extents_slices_t {
public:
    implementation_t();

    ~implementation_t();

    std::pair<int, int> evaluate(evaluate_options_t, int width, int height);
    std::pair<int, int> adjust(evaluate_options_t options, int width, int height);
    iterator add_placeable(iterator parent, const layout_attributes_t& initial,
                           bool is_container_type, poly_placeable_t& placeable, bool reverse);
    void set_visible(iterator, bool);

private:
    void solve(slice_select_t select);
    void layout(slice_select_t select, int optional_length);

    typedef edge_iterator<cursor, adobe::forest_trailing_edge> postorder_iterator;
    typedef edge_iterator<cursor, adobe::forest_leading_edge> preorder_iterator;

    boost::iterator_range<postorder_iterator> postorder_range() {
        return adobe::postorder_range(filter_fullorder_range(proxies_m, filter_visible()));
    }

    boost::iterator_range<preorder_iterator> preorder_range() {
        return adobe::preorder_range(filter_fullorder_range(proxies_m, filter_visible()));
    }

    proxy_tree_t proxies_m;
};

/**************************************************************************************************/

#if !defined(ADOBE_NO_DOCUMENTATION)
eve_t::eve_t() : object_m(new implementation_t()) {}

eve_t::~eve_t() { delete object_m; }
#endif

std::pair<int, int> eve_t::evaluate(evaluate_options_t options, int width, int height) {
    return object_m->evaluate(options, width, height);
}

std::pair<int, int> eve_t::adjust(evaluate_options_t options, int width, int height) {
    return object_m->adjust(options, width, height);
}

eve_t::iterator eve_t::add_placeable(iterator parent, const layout_attributes_t& initial,
                                     bool is_container_type,      // is the element a container?
                                     poly_placeable_t& placeable, // signals to call for the element
                                     bool reverse) {
    return object_m->add_placeable(parent, initial, is_container_type, placeable, reverse);
}

void eve_t::set_visible(iterator c, bool visible) { return object_m->set_visible(c, visible); }

/**************************************************************************************************/

#if 0
#pragma mark -
#endif

/**************************************************************************************************/

eve_t::implementation_t::implementation_t() {}

/**************************************************************************************************/

eve_t::implementation_t::~implementation_t() {}

/**************************************************************************************************/

/*
    REVISIT (sparent) : This logic would be simplified with a root() function wich could be passed
    as the initial parent.
*/

eve_t::iterator eve_t::implementation_t::add_placeable(iterator parent,
                                                       const layout_attributes_t& initial,
                                                       bool is_container_type,
                                                       poly_placeable_t& placeable, bool reverse) {
    if (parent == iterator())
        parent = proxies_m.end();

    parent = proxies_m.insert(reverse ? boost::next(adobe::leading_of(parent))
                                      : adobe::trailing_of(parent),
                              implementation::view_proxy_t(initial, placeable));

    if (!is_container_type)
        parent->geometry_m.placement_m = place_leaf;

    return parent;
}

/**************************************************************************************************/

void eve_t::implementation_t::set_visible(iterator c, bool visible) { c->visible_m = visible; }

/**************************************************************************************************/

void eve_t::implementation_t::solve(slice_select_t select) {
    adobe::for_each_position(
        postorder_range(),
        apply_to_children<postorder_iterator>(&implementation::view_proxy_t::solve_up, select));

    // REVISIT (sparent) : HUGE opportunities to optimize this.

    // solve until things settle down.

    bool progress(false);

    /*
        REVISIT (sparent) : This loop should solve it in rougly log N passes
        We know that we are guaranteed to solve one guide completely per iteration
        and most often it should be several. But, I've been known to make a mistake or two
        (which could cause this loop to solve forever!). So we put a limiter on it and
        an assert.

    */
    proxy_tree_t::size_type limiter(proxies_m.size() + 1); // + 1 to account for the empty case

    do {
        --limiter;
        progress = false;

        for (preorder_iterator first(boost::begin(preorder_range())),
             last(boost::end(preorder_range()));
             first != last; ++first) {
            progress |=
                first->solve_down(::child_begin(first.base()), ::child_end(first.base()), select);
        }

        adobe::for_each_position(postorder_range(),
                                 ::apply_to_children<postorder_iterator>(
                                     &implementation::view_proxy_t::solve_up, select));

    } while (progress && limiter);

    assert(limiter); // Failing to make forward progress - aborting.
}

/**************************************************************************************************/

void eve_t::implementation_t::layout(slice_select_t select, int optional_length) {
    // FILTER VISIBLE - this assumes a visible root

    if (!proxies_m.empty()) {
        place_data_t::slice_t& pslice(proxies_m.front().place_m.slice_m[select]);

        /*
            REVISIT (sparent) : This allows us to go sub-minimum. May revisit for wrapped
            containers.
        */

        pslice.length_m =
            optional_length ? optional_length : proxies_m.front().container_length_m[select];
    }

    adobe::for_each_position(preorder_range(), apply_to_children<preorder_iterator>(
                                                   &implementation::view_proxy_t::layout, select));
}

/**************************************************************************************************/

std::pair<int, int> eve_t::implementation_t::evaluate(evaluate_options_t options, int width,
                                                      int height) {
    // Calculate

    adobe::for_each(postorder_range(), &proxy_tree_t::value_type::calculate);

    // adjust

    return adjust(options, width, height);
}

/**************************************************************************************************/

std::pair<int, int> eve_t::implementation_t::adjust(evaluate_options_t options, int width,
                                                    int height) {
    // adjust

    adobe::for_each_position(
        postorder_range(),
        apply_to_children<postorder_iterator>(&implementation::view_proxy_t::adjust, horizontal));

    // solve

    solve(horizontal); // Not necessary
    layout(horizontal, width);

    // adjust outsets

    adobe::for_each_position(postorder_range(),
                             apply_to_children<postorder_iterator>(
                                 &implementation::view_proxy_t::adjust_outsets, horizontal));

    // flatten

    adobe::for_each_position(preorder_range(), apply_flatten_t(horizontal, options));

    // give the client a crack at adjusting vertical

    adobe::for_each(postorder_range(), &proxy_tree_t::value_type::calculate_vertical);

    // adjust

    adobe::for_each_position(
        postorder_range(),
        apply_to_children<postorder_iterator>(&implementation::view_proxy_t::adjust, vertical));

    // solve

    solve(vertical);
    layout(vertical, height);

    // adjust outsets

    adobe::for_each_position(postorder_range(),
                             apply_to_children<postorder_iterator>(
                                 &implementation::view_proxy_t::adjust_outsets, vertical));

    // flatten

    adobe::for_each_position(preorder_range(), apply_flatten_t(vertical, options));

    // place

    adobe::for_each(preorder_range(), &proxy_tree_t::value_type::place);

    return std::make_pair(proxies_m.front().place_m.horizontal().length_m,
                          proxies_m.front().place_m.vertical().length_m);
}

/**************************************************************************************************/

#if 0
#pragma mark -
#endif

/**************************************************************************************************/

namespace implementation {

/**************************************************************************************************/

struct calculate : public boost::static_visitor<> {
    template <typename T>
    void operator()(T& operand) const {
        operand += operand;
    }
};

/**************************************************************************************************/

view_proxy_t::view_proxy_t(const adobe::layout_attributes_t& d, poly_placeable_t& p)
    : placeable_m(p), visible_m(true), geometry_m(d) {}

/**************************************************************************************************/

void view_proxy_t::calculate() {
    /*
        REVISIT (sparent) : What we want is for the data from placeable widgets to be preserved
        unless they are explicity dirtied - rather than calling measure for every update.
        For now, there are several bugs caused by the measuring code in widgets assuming that
       the
        initial extents it is handed is a defaulted extents. Without that - some code
       accumulates
        metrics into the extents giving ever increasing growth when a window is resized (as an
        example). This fix is a hack - to just always clear the extents before measuring.
    */
    geometry_m.extents_m = extents_t();

    placeable_m.measure(geometry_m.extents_m);

    extents_t::slice_t& eslice = geometry_m.extents_m.horizontal();

    place_m.horizontal().length_m = eslice.length_m;
    place_m.horizontal().outset_m = eslice.outset_m;

    // Copy the guides over. Only non-surpressed guides will be updated.
    place_m.horizontal().guide_set_m = eslice.guide_set_m;

    /*
        REVISIT (sparent) : It becomes apparent here that we have a number of limitation which
        we should address:

        1. Containers cannot have their own guides to align items in their frame.
        2. Leaf nodes effectively have thier guides surpressed if they are aligned by anything
       other
            than forward or reverse. Should probably allow for fill, but that would make fill
            orthoganal to alignment.
    */

    /*
        REVISIT (sparent) : The vertical data should also be handled here to avoid the
       peformance
        hit in calculate_vertical() during a resize. I'll factor this code later.
    */

    container_length_m[horizontal] = eslice.length_m;
}

/**************************************************************************************************/

void view_proxy_t::calculate_vertical() {
    extents_t::slice_t& eslice = geometry_m.extents_m.vertical();

    if (poly_placeable_twopass_t* p = poly_cast<poly_placeable_twopass_t*>(&placeable_m)) {
        // We pass a copy of the geometry so client can't modify horizontal properties.
        extents_t vertical_stuff(geometry_m.extents_m);
        p->measure_vertical(vertical_stuff, place_m);
        eslice = vertical_stuff.vertical();
    }

    place_m.vertical().length_m = eslice.length_m;
    place_m.vertical().outset_m = eslice.outset_m;

    // Copy the guides over. Only non-surpressed guides will be updated.
    place_m.vertical().guide_set_m = eslice.guide_set_m;

    container_length_m[vertical] = eslice.length_m;
}

/**************************************************************************************************/

void view_proxy_t::place() { placeable_m.place(place_m); }

/**************************************************************************************************/

void view_proxy_t::adjust(::child_iterator first, ::child_iterator last, slice_select_t select) {
    if (geometry_m.placement_m == eve_t::place_leaf)
        return;

    for (::child_iterator iter(first); iter != last; ++iter) {
        layout_attributes_t::alignment_t& child_alignment(
            iter->geometry_m.slice_m[select].alignment_m);

        if (child_alignment == layout_attributes_t::align_default) {
            child_alignment = geometry_m.slice_m[select].child_alignment_m;
        }

        /*
            Now that we know the final alignment - we can copy the guides to the container
           guides.
            This is only done on leaf nodes because the guides will be propogated to the
           containers
            through either adjust_with or _cross.
        */
        if (iter->geometry_m.placement_m == eve_t::place_leaf) {
            switch (child_alignment) {
            case layout_attributes_t::align_forward:
            case layout_attributes_t::align_forward_fill: {
                iter->container_guide_set_m[select][layout_attributes_t::align_forward] =
                    iter->geometry_m.extents_m.slice_m[select].guide_set_m;
            } break;
            case layout_attributes_t::align_reverse:
            case layout_attributes_t::align_reverse_fill: {
                guide_set_t& guide_set(
                    iter->container_guide_set_m[select][layout_attributes_t::align_reverse]);

                guide_set = iter->geometry_m.extents_m.slice_m[select].guide_set_m;

                adobe::transform(guide_set, boost::begin(guide_set),
                                 boost::bind(std::minus<int>(),
                                             iter->geometry_m.extents_m.slice_m[select].length_m,
                                             _1));
                adobe::reverse(guide_set);
            } break;
            default:
                break;
            }
        }
    }

    if (is_with(geometry_m.placement_m, select))
        adjust_with(first, last, select);
    else
        adjust_cross(first, last, select);
}

/**************************************************************************************************/

void view_proxy_t::solve_up(::child_iterator first, ::child_iterator last, slice_select_t select) {
    if (geometry_m.placement_m == adobe::eve_t::place_leaf)
        return;

    if (select == vertical) {
        if (geometry_m.placement_m == adobe::eve_t::place_column)
            solve_up_with(first, last, vertical);
        else
            solve_up_cross(first, last, vertical);
    } else {
        if (geometry_m.placement_m == adobe::eve_t::place_row)
            solve_up_with(first, last, horizontal);
        else
            solve_up_cross(first, last, horizontal);
    }
}

/**************************************************************************************************/

bool view_proxy_t::solve_down(::child_iterator first, ::child_iterator last,
                              slice_select_t select) {
    bool result(false);

    if (geometry_m.placement_m == adobe::eve_t::place_leaf)
        return result;

    if (select == vertical) {
        if (geometry_m.placement_m == adobe::eve_t::place_column)
            result |= solve_down_with(first, last, vertical);
        else
            result |= solve_down_cross(first, last, vertical);
    } else {
        if (geometry_m.placement_m == adobe::eve_t::place_row)
            result |= solve_down_with(first, last, horizontal);
        else
            result |= solve_down_cross(first, last, horizontal);
    }

    return result;
}

/**************************************************************************************************/

void view_proxy_t::layout(::child_iterator first, ::child_iterator last, slice_select_t select) {
    if (geometry_m.placement_m == adobe::eve_t::place_leaf)
        return;

    if (select == vertical) {
        if (geometry_m.placement_m == adobe::eve_t::place_column)
            layout_with(first, last, vertical);
        else
            layout_cross(first, last, vertical);
    } else {
        if (geometry_m.placement_m == adobe::eve_t::place_row)
            layout_with(first, last, horizontal);
        else
            layout_cross(first, last, horizontal);
    }
}

/**************************************************************************************************/

void view_proxy_t::flatten(::child_iterator first, ::child_iterator last, slice_select_t select,
                           adobe::eve_t::evaluate_options_t options) {
    // Push the guides into the element being placed.

    guide_set_t& guide_set(place_m.slice_m[select].guide_set_m);

    switch (geometry_m.slice_m[select].alignment_m) {
    case layout_attributes_t::align_forward:
    case layout_attributes_t::align_forward_fill: {
        guide_set = container_guide_set_m[select][layout_attributes_t::align_forward];
    } break;
    case layout_attributes_t::align_reverse:
    case layout_attributes_t::align_reverse_fill: {
        guide_set = container_guide_set_m[select][layout_attributes_t::align_reverse];
        adobe::transform(guide_set, boost::begin(guide_set),
                         boost::bind(std::minus<int>(), place_m.slice_m[select].length_m, _1));
        adobe::reverse(guide_set);
    } break;
    default:
        break;
    }

    // Flatten the coordinate system if needed for the children.

    if (options == adobe::eve_t::evaluate_nested && geometry_m.create_m)
        return;

    int position(place_m.slice_m[select].position_m);

    for (; first != last; ++first) {
        first->place_m.slice_m[select].position_m += position;
    }
}

/**************************************************************************************************/

void view_proxy_t::adjust_outsets(::child_iterator first, ::child_iterator last,
                                  slice_select_t select) {
    if (select == vertical) {
        if (geometry_m.placement_m == adobe::eve_t::place_column)
            adjust_outsets_with(first, last, vertical);
        else
            adjust_outsets_cross(first, last, vertical);
    } else {
        if (geometry_m.placement_m == adobe::eve_t::place_row)
            adjust_outsets_with(first, last, horizontal);
        else
            adjust_outsets_cross(first, last, horizontal);
    }
}

/**************************************************************************************************/

void view_proxy_t::adjust_outsets_with(::child_iterator first, ::child_iterator last,
                                       slice_select_t select) {
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    place_data_t::slice_t& pslice(place_m.slice_m[select]);

    if (first == last) {
        pslice.outset_m = eslice.outset_m;
        return;
    }

    --last;

    adobe::place_data_t::slice_t& leading_pslice(first->place_m.slice_m[select]);
    adobe::place_data_t::slice_t& trailing_pslice(last->place_m.slice_m[select]);

    int leading_outset_position = leading_pslice.position_m - leading_pslice.outset_m.first;

    // trailing_outset_position is measured as distance from edge to inside (like frame)
    int trailing_outset_position =
        pslice.length_m -
        (trailing_pslice.position_m + trailing_pslice.length_m + trailing_pslice.outset_m.second);

// REVISIT (sparent) : We need a warning mechanism to report this issue!
#ifndef NDEBUG
    if (!(!eslice.frame_m.first || (leading_outset_position >= eslice.frame_m.first))) {
        std::cerr << "WARNING (sparent) : outset collision." << std::endl;
    }
#endif

    pslice.outset_m.first = std::max(pslice.outset_m.first, -leading_outset_position);

#ifndef NDEBUG
    if (!(!eslice.frame_m.second || (trailing_outset_position >= eslice.frame_m.second))) {
        std::cerr << "WARNING (sparent) : outset collision." << std::endl;
    }
#endif

    pslice.outset_m.second = std::max(pslice.outset_m.second, -trailing_outset_position);
}

/**************************************************************************************************/

void view_proxy_t::adjust_outsets_cross(::child_iterator first, ::child_iterator last,
                                        slice_select_t select) {
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    place_data_t::slice_t& pslice(place_m.slice_m[select]);

    if (first == last) {
        pslice.outset_m = eslice.outset_m;
        return;
    }

    // start by assuming enough space for the frame.
    int leading_outset_position = eslice.frame_m.first;
    int trailing_outset_position = eslice.frame_m.second;

    for (::child_iterator iter(first); iter != last; ++iter) {
        place_data_t::slice_t& iter_pslice(iter->place_m.slice_m[select]);

        leading_outset_position =
            std::min(leading_outset_position, iter_pslice.position_m - iter_pslice.outset_m.first);

        // trailing_outset_position is measured as distance from edge to inside (like frame)
        trailing_outset_position =
            std::min(trailing_outset_position,
                     pslice.length_m - (iter_pslice.position_m + iter_pslice.length_m +
                                        iter_pslice.outset_m.second));
    }

// REVISIT (sparent) : We need a warning mechanism to report this issue!
#ifndef NDEBUG
    if (!(!eslice.frame_m.first || (leading_outset_position >= eslice.frame_m.first))) {
        std::cerr << "WARNING (sparent) : outset collision." << std::endl;
    }
#endif

    pslice.outset_m.first = std::max(pslice.outset_m.first, -leading_outset_position);

#ifndef NDEBUG
    if (!(!eslice.frame_m.second || (trailing_outset_position >= eslice.frame_m.second))) {
        std::cerr << "WARNING (sparent) : outset collision." << std::endl;
    }
#endif

    pslice.outset_m.second = std::max(pslice.outset_m.second, -trailing_outset_position);
}

/**************************************************************************************************/

void view_proxy_t::layout_with(::child_iterator first, ::child_iterator last,
                               slice_select_t select) {
    if (first == last)
        return;

    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    place_data_t::slice_t& pslice(place_m.slice_m[select]);

    /*
    REVISIT (sparent) : Something to think about. Counting the number of children could be
    expressed as count_if that takes a "within set" as a predicate.
    */

    /*
    REVISIT (sparent) : The extra space should be destributed to the items in blocks - up to the
    first guide, then to the next.
    */

    // count the number of children to distribute any additional space

    int padded_count(0);

    for (::child_iterator iter(first); iter != last; ++iter) {

        switch (iter->geometry_m.slice_m[select].alignment_m) {
        case adobe::layout_attributes_t::align_center:
        case adobe::layout_attributes_t::align_proportional:
        case adobe::layout_attributes_t::align_forward_fill:
        case adobe::layout_attributes_t::align_reverse_fill:
            ++padded_count;
            break;
        default:
            break;
        }
    }

    // calculate the additional per/item space

    int remaining_additional_length(pslice.length_m - measured_length_m[select]);

    int available_length(pslice.length_m - gslice.margin_m.first - gslice.margin_m.second -
                         eslice.frame_m.first - eslice.frame_m.second);

    // place any reverse align items
    int rlength = pslice.length_m - (gslice.margin_m.second + eslice.frame_m.second);

    ::reverse_child_iterator riter(last);
    ::reverse_child_iterator rlast(first);

    guide_set_t::iterator reverse_guide_iter(
        container_guide_set_m[select][layout_attributes_t::align_reverse].begin());

    for (; riter != rlast; ++riter) {
        const layout_attributes_t::slice_t& iter_gslice(riter->geometry_m.slice_m[select]);

        if (iter_gslice.alignment_m != layout_attributes_t::align_reverse &&
            iter_gslice.alignment_m != layout_attributes_t::align_reverse_fill)
            break;

        place_data_t::slice_t& iter_pslice(riter->place_m.slice_m[select]);
        guide_set_t& reverse_child_guide_set(
            riter->container_guide_set_m[select][layout_attributes_t::align_reverse]);

        iter_pslice.length_m = riter->container_length_m[select];

        // These items are offset by their guides

        if (!iter_gslice.suppress_m && reverse_child_guide_set.size()) {
            if (riter->geometry_m.placement_m == eve_t::place_leaf) {
                rlength -= *reverse_guide_iter - reverse_child_guide_set.front();
            }
            std::advance(reverse_guide_iter,
                         guide_set_t::difference_type(reverse_child_guide_set.size()));
        }

        /*
            REVISIT (sparent) : Filled items fill forward. The space to behind is going to
            be dead space... It would be good to allow it to be filled.
        */

        if (iter_gslice.alignment_m == adobe::layout_attributes_t::align_reverse_fill) {

            int additional_length(remaining_additional_length / padded_count);

            --padded_count;
            remaining_additional_length -= additional_length;

            iter_pslice.length_m = riter->container_length_m[select] + additional_length;
        }

        iter_pslice.position_m = rlength - iter_pslice.length_m;

        rlength -= iter_pslice.length_m + riter->space_before_m;
    }

    // place any forward items

    int zero_length = gslice.margin_m.first + eslice.frame_m.first;
    int length = zero_length;

    guide_set_t::iterator guide_iter(
        container_guide_set_m[select][layout_attributes_t::align_forward].begin());

    for (::child_iterator iter(first); iter != riter.base(); ++iter) {
        const layout_attributes_t::slice_t& iter_gslice(iter->geometry_m.slice_m[select]);
        place_data_t::slice_t& iter_pslice(iter->place_m.slice_m[select]);

        guide_set_t& forward_child_guide_set(
            iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

        length += iter->space_before_m;

        if (iter_gslice.alignment_m != adobe::layout_attributes_t::align_fill) {
            iter_pslice.length_m = iter->container_length_m[select];
        }

        int additional_length(0);

        switch (iter_gslice.alignment_m) {
        case adobe::layout_attributes_t::align_forward_fill:
        case adobe::layout_attributes_t::align_center:
        case adobe::layout_attributes_t::align_proportional: {
            additional_length = remaining_additional_length / padded_count;
            --padded_count;
            remaining_additional_length -= additional_length;
        } break;
        default:
            break;
        }

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill: {
            // These items are offset by their guides

            if (!iter_gslice.suppress_m && forward_child_guide_set.size()) {
                if (iter->geometry_m.placement_m == eve_t::place_leaf) {
                    length = *guide_iter - forward_child_guide_set.front();
                }
                std::advance(guide_iter,
                             guide_set_t::difference_type(forward_child_guide_set.size()));
            }

            /*
                REVISIT (sparent) : Filled items fill forward. The space to behind is going to
                be dead space... It would be good to allow it to be filled.
            */

            if (iter_gslice.alignment_m == adobe::layout_attributes_t::align_forward_fill) {
                iter_pslice.length_m = iter->container_length_m[select] + additional_length;
            }

            iter_pslice.position_m = length;
        } break;
        case adobe::layout_attributes_t::align_center: {
            int block_length(iter->container_length_m[select] + additional_length);
            iter_pslice.position_m = length + (block_length - iter->container_length_m[select]) / 2;
            length += additional_length;
        } break;
        case adobe::layout_attributes_t::align_proportional: {
            int block_length(iter->container_length_m[select] + additional_length);
            double proportion(double(length - zero_length) /
                              double(available_length - block_length));
            iter_pslice.position_m = length + adobe::lround_half_up(proportion * additional_length);
            length += additional_length;
        } break;
        case adobe::layout_attributes_t::align_reverse:
        case adobe::layout_attributes_t::align_reverse_fill:
            /*
                REVISIT (sparent) : This is a runtime error and needs to go through the stream
                error reporting mechanism.
            */
            throw std::logic_error("Right align item before other item.");
        default:
            break;
        }

        length += iter_pslice.length_m;
    }
}

/**************************************************************************************************/

void view_proxy_t::layout_cross(::child_iterator first, ::child_iterator last,
                                slice_select_t select) {
    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    place_data_t::slice_t& pslice(place_m.slice_m[select]);

    // calculate a base for the child position.

    int length = gslice.margin_m.first + eslice.frame_m.first;
    int rlength = pslice.length_m - (gslice.margin_m.second + eslice.frame_m.second);

    for (::child_iterator iter(first); iter != last; ++iter) {
        const layout_attributes_t::slice_t& iter_gslice(iter->geometry_m.slice_m[select]);
        place_data_t::slice_t& iter_pslice(iter->place_m.slice_m[select]);

        guide_set_t& forward_child_guide_set(
            iter->container_guide_set_m[select][layout_attributes_t::align_forward]);
        guide_set_t& reverse_child_guide_set(
            iter->container_guide_set_m[select][layout_attributes_t::align_reverse]);

        if (iter_gslice.alignment_m != adobe::layout_attributes_t::align_fill) {
            iter_pslice.length_m = iter->container_length_m[select];
        }

        int iter_length(length);
        int iter_rlength(rlength);

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
            iter_length += iter->geometry_m.indent_m;
            break;
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
            iter_rlength -= iter->geometry_m.indent_m;
            break;
        default:
            break;
        }

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill: {
            if ((iter->geometry_m.placement_m == eve_t::place_leaf) && !iter_gslice.suppress_m &&
                forward_child_guide_set.size()) {
                iter_length =
                    container_guide_set_m[select][layout_attributes_t::align_forward].front() -
                    forward_child_guide_set.front();
            }

            if (iter_gslice.alignment_m == layout_attributes_t::align_forward_fill) {
                iter_pslice.length_m = iter_rlength - iter_length;
            }

            iter_pslice.position_m = iter_length;
        } break;
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill: {
            if ((iter->geometry_m.placement_m == eve_t::place_leaf) && !iter_gslice.suppress_m &&
                reverse_child_guide_set.size()) {
                iter_rlength =
                    pslice.length_m -
                    (container_guide_set_m[select][layout_attributes_t::align_reverse].front() -
                     reverse_child_guide_set.front());
            }

            if (iter_gslice.alignment_m == layout_attributes_t::align_reverse_fill) {
                iter_pslice.length_m = iter_rlength - iter_length;
            }

            iter_pslice.position_m = iter_rlength - iter->container_length_m[select];
        } break;
        case layout_attributes_t::align_center:
        case layout_attributes_t::align_proportional:
            iter_pslice.position_m =
                (iter_rlength + iter_length - iter->container_length_m[select]) / 2;
            break;
        default:
            break;
        }
    }
}

/**************************************************************************************************/

void view_proxy_t::adjust_with(::child_iterator first, ::child_iterator last,
                               slice_select_t select) {
    // set the spacing for each of our children.

    /*
    REVISIT (sparent) : I'm still struggling to write a concise version of this section.

    Things to note:
        1. we need a make_tranform_range().
        2. This function should be passed _range_ instead of first, last.
        3. complain to boost again about bind/mem_fn not dealing with non-const member
    references.

    ----

    typedef adobe::mem_data_t<view_proxy_t, int>            transform_function;
    typedef boost::transform_iterator<transform_function>   tranform_iterator;
    typedef boost::tranform_range<tranform_iterator>        tranform_range;

    tranform_range child_spacing_range(
            adobe::make_tranform_range(range, adobe::mem_data(&view_proxy_t::space_before_m));

    assert(!geometry_m.spacing_m.empty());

    std::fill(
        adobe::copy_bound(geometry.spacing_m, child_spacing_range).second,
        boost::end(child_spacing_range), geometry_m.spacing_m.back());
    */

    typedef layout_attributes_t::spacing_t::difference_type difference_type;

    const difference_type copy_count(std::min(difference_type(geometry_m.spacing_m.size()),
                                              difference_type(std::distance(first, last))));

    assert(!geometry_m.spacing_m.empty());

    std::fill(std::copy(geometry_m.spacing_m.begin(), geometry_m.spacing_m.begin() + copy_count,
                        boost::make_transform_iterator(
                            first, adobe::mem_data(&view_proxy_t::space_before_m))),
              boost::make_transform_iterator(last, adobe::mem_data(&view_proxy_t::space_before_m)),
              geometry_m.spacing_m.back());

    // size the container guide set based on the number of guides our children have.

    /*
    REVISIT (sparent) : I'm sure there is oportunity to do less work here but we clear the
    guides
    so we can re-adjust on a size adjust.
    */

    container_guide_set_m[select][layout_attributes_t::align_forward].clear();
    container_guide_set_m[select][layout_attributes_t::align_reverse].clear();

    /*
    REVISIT (sparent) : This is a good candidate for using boost::lambda and accumlate.
    There may also be the notion of an iterator adaptor that adapts iterator to pointer
    to behave as a simple iterator.
    */

    std::size_t forward_guide_count(0);
    std::size_t reverse_guide_count(0);

    for (::child_iterator iter(first); iter != last; ++iter) {
        layout_attributes_t::slice_t& gslice(iter->geometry_m.slice_m[select]);
        if (!gslice.suppress_m) {
            switch (gslice.alignment_m) {
            case layout_attributes_t::align_forward: {
                forward_guide_count +=
                    iter->container_guide_set_m[select][layout_attributes_t::align_forward].size();
            } break;
            case layout_attributes_t::align_reverse: {
                reverse_guide_count +=
                    iter->container_guide_set_m[select][layout_attributes_t::align_reverse].size();
            } break;
            case layout_attributes_t::align_forward_fill:
            case layout_attributes_t::align_reverse_fill: {
                forward_guide_count +=
                    iter->container_guide_set_m[select][layout_attributes_t::align_forward].size();
                reverse_guide_count +=
                    iter->container_guide_set_m[select][layout_attributes_t::align_reverse].size();
            } break;
            default:
                gslice.suppress_m = true;
                break;
            }
        }
    }

    container_guide_set_m[select][layout_attributes_t::align_forward].resize(forward_guide_count);
    container_guide_set_m[select][layout_attributes_t::align_reverse].resize(reverse_guide_count);
}

/**************************************************************************************************/

void view_proxy_t::adjust_cross(::child_iterator first, ::child_iterator last,
                                slice_select_t select) {
    // size the container guide set based on the number of guides our children have.

    /*
    REVISIT (sparent) : I'm sure there is oportunity to do less work here but we clear the
    guides
    so we can re-adjust on a size adjust.
    */

    container_guide_set_m[select][layout_attributes_t::align_forward].clear();
    container_guide_set_m[select][layout_attributes_t::align_reverse].clear();

    /*
    REVISIT (sparent) : This is a good candidate for using boost::lambda and accumlate.
    There may also be the notion of an iterator adaptor that adapts iterator to pointer
    to behave as a simple iterator.
    */

    std::size_t forward_guide_count(0);
    std::size_t reverse_guide_count(0);

    for (::child_iterator iter(first); iter != last; ++iter) {
        layout_attributes_t::slice_t& gslice(iter->geometry_m.slice_m[select]);

        if (gslice.suppress_m)
            continue;

        switch (gslice.alignment_m) {
        case layout_attributes_t::align_forward: {
            forward_guide_count = std::max(
                forward_guide_count,
                iter->container_guide_set_m[select][layout_attributes_t::align_forward].size());
        } break;
        case layout_attributes_t::align_reverse: {
            reverse_guide_count = std::max(
                reverse_guide_count,
                iter->container_guide_set_m[select][layout_attributes_t::align_reverse].size());
        } break;
        case layout_attributes_t::align_forward_fill:
        case layout_attributes_t::align_reverse_fill: {
            forward_guide_count = std::max(
                forward_guide_count,
                iter->container_guide_set_m[select][layout_attributes_t::align_forward].size());
            reverse_guide_count = std::max(
                reverse_guide_count,
                iter->container_guide_set_m[select][layout_attributes_t::align_reverse].size());
        } break;
        default:
            gslice.suppress_m = true;
            break;
        }
    }

    container_guide_set_m[select][layout_attributes_t::align_forward].resize(forward_guide_count);
    container_guide_set_m[select][layout_attributes_t::align_reverse].resize(reverse_guide_count);
}

/**************************************************************************************************/

void view_proxy_t::solve_up_with(::child_iterator first, ::child_iterator last,
                                 slice_select_t select) {
    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    int length(eslice.frame_m.first + gslice.margin_m.first);
    int rlength(eslice.frame_m.second + gslice.margin_m.second);

    guide_set_t& forward_guide_set(
        container_guide_set_m[select][layout_attributes_t::align_forward]);
    guide_set_t& reverse_guide_set(
        container_guide_set_m[select][layout_attributes_t::align_reverse]);
    guide_set_t::iterator forward_guide_iter(forward_guide_set.begin());
    guide_set_t::iterator reverse_guide_iter(reverse_guide_set.begin());

    int additional_rlength(rlength);

    // accumulate the length and update the position.

    for (::reverse_child_iterator rfirst(last), rlast(first); rfirst != rlast; ++rfirst) {
        switch (rfirst->geometry_m.slice_m[select].alignment_m) {
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
        case layout_attributes_t::align_forward_fill: {
            if (rfirst->geometry_m.slice_m[select].suppress_m)
                break;

            guide_set_t::iterator reverse_first_guide(reverse_guide_iter);
            guide_set_t& reverse_child_guide_set(
                rfirst->container_guide_set_m[select][layout_attributes_t::align_reverse]);

            for (guide_set_t::iterator guide(reverse_child_guide_set.begin());
                 guide != reverse_child_guide_set.end(); ++guide, ++reverse_guide_iter) {
                assert(reverse_guide_iter != reverse_guide_set.end());
                *reverse_guide_iter = std::max(*reverse_guide_iter, *guide + rlength);
            }

            if ((rfirst->geometry_m.placement_m == adobe::eve_t::place_leaf) &&
                reverse_child_guide_set.size()) {
                assert(reverse_first_guide != reverse_guide_set.end());
                int current_rlength(rlength);
                rlength = *reverse_first_guide - reverse_child_guide_set.front();
                additional_rlength += rlength - current_rlength;
            }
        } break;
        default:
            break;
        }

        rlength += rfirst->container_length_m[select] + rfirst->space_before_m;
    }

    for (::child_iterator iter(first); iter != last; ++iter) {
        length += iter->space_before_m;

        switch (iter->geometry_m.slice_m[select].alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
        case layout_attributes_t::align_reverse_fill: {
            if (iter->geometry_m.slice_m[select].suppress_m)
                break;

            guide_set_t::iterator forward_first_guide(forward_guide_iter);
            guide_set_t& forward_child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

            for (guide_set_t::iterator guide(forward_child_guide_set.begin());
                 guide != forward_child_guide_set.end(); ++guide, ++forward_guide_iter) {
                assert(forward_guide_iter != forward_guide_set.end());
                *forward_guide_iter = std::max(*forward_guide_iter, *guide + length);
            }

            if ((iter->geometry_m.placement_m == adobe::eve_t::place_leaf) &&
                forward_child_guide_set.size()) {
                assert(forward_first_guide != forward_guide_set.end());
                length = *forward_first_guide - forward_child_guide_set.front();
            }
        } break;
        default:
            break;
        }

        length += iter->container_length_m[select];
    }

    // balance the guides

    if (gslice.balance_m && forward_guide_set.size() > 2) {
        guide_set_t::iterator iter(adobe::max_adjacent_difference(forward_guide_set));
        guide_set_t::value_type difference(*boost::next(iter) - *iter);

        guide_set_t::value_type accumulate(forward_guide_set.front());

        /*
        REVISIT (sparent) : This should be a call to generate - but I need a simple to create
        accumulate function object.
        */

        for (guide_set_t::iterator first(boost::next(forward_guide_set.begin())),
             last(forward_guide_set.end());
             first != last; ++first) {
            accumulate += difference;
            *first = accumulate;
        }
    }

    length += additional_rlength;

    // update properties on this container.

    measured_length_m[select] = length;
    container_length_m[select] = std::max(length, container_length_m[select]);
}

/**************************************************************************************************/

bool view_proxy_t::solve_down_with(::child_iterator first, ::child_iterator last,
                                   slice_select_t select) {
    bool result(false);
    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    int length(eslice.frame_m.first + gslice.margin_m.first);
    int rlength(eslice.frame_m.second + gslice.margin_m.second);
    guide_set_t::iterator guide_iter(
        container_guide_set_m[select][layout_attributes_t::align_forward].begin());
    guide_set_t::iterator reverse_guide_iter(
        container_guide_set_m[select][layout_attributes_t::align_reverse].begin());

    // accumulate the length and update the position.

    /*
        REVISIT (sparent) : After we move the guides on a container we don't know if we need to
        move the guides on subsequent children because the container may (or may not) grow in
        response. If it grows, it will shift the sibling over, which may resolve the guide for
       us.

        Becuase of this, we break out of this loop once we've adjusted one guide on one
       container.
        ... I suspect there is a pathelogical case here that's tending towards N^2. I need to
        revist how we are solving but the actual case where this happens is complex enough
        (requiring 4 levels of nesting with two guides) that I don't think it is a huge problem.
    */

    for (::reverse_child_iterator rfirst(last), rlast(first); rfirst != rlast && !result;
         ++rfirst) {
        switch (rfirst->geometry_m.slice_m[select].alignment_m) {
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
        case layout_attributes_t::align_forward_fill: {
            if (rfirst->geometry_m.slice_m[select].suppress_m)
                break;

            guide_set_t& child_guide_set(
                rfirst->container_guide_set_m[select][layout_attributes_t::align_reverse]);

            guide_set_t::iterator guide(child_guide_set.begin());
            guide_set_t::iterator guide_last(child_guide_set.end());

            if ((rfirst->geometry_m.placement_m == eve_t::place_leaf) && guide != guide_last) {
                // Snap the current postion to the guide.
                assert(reverse_guide_iter !=
                       container_guide_set_m[select][layout_attributes_t::align_reverse].end());
                rlength = *reverse_guide_iter++ - *guide++;
            }

            for (; guide != guide_last; ++guide, ++reverse_guide_iter) {
                assert(reverse_guide_iter !=
                       container_guide_set_m[select][layout_attributes_t::align_reverse].end());
                int new_guide(*reverse_guide_iter - rlength);

                if (new_guide != *guide) {
                    result = true;
                    *guide = new_guide;
                }
            }
        } break;
        default:
            break;
        }

        rlength += rfirst->container_length_m[select] + rfirst->space_before_m;
    }

    if (result)
        return result;

    for (::child_iterator iter(first); (iter != last) && !result; ++iter) {
        length += iter->space_before_m;

        switch (iter->geometry_m.slice_m[select].alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
        case layout_attributes_t::align_reverse_fill: {
            if (iter->geometry_m.slice_m[select].suppress_m)
                break;

            guide_set_t& child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

            guide_set_t::iterator guide(child_guide_set.begin());
            guide_set_t::iterator guide_last(child_guide_set.end());

            if ((iter->geometry_m.placement_m == adobe::eve_t::place_leaf) && guide != guide_last) {
                // Snap the current postion to the guide.
                assert(guide_iter !=
                       container_guide_set_m[select][layout_attributes_t::align_forward].end());
                length = *guide_iter++ - *guide++;
            }

            for (; guide != guide_last; ++guide, ++guide_iter) {
                assert(guide_iter !=
                       container_guide_set_m[select][layout_attributes_t::align_forward].end());
                int new_guide(*guide_iter - length);

                if (new_guide != *guide) {
                    result = true;
                    *guide = new_guide;
                }
            }
        } break;
        default:
            break;
        }

        length += iter->container_length_m[select];
    }

    return result;
}

/**************************************************************************************************/

void view_proxy_t::solve_up_cross(::child_iterator first, ::child_iterator last,
                                  slice_select_t select) {
    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    int near_additional(eslice.frame_m.first + gslice.margin_m.first);
    int far_additional(eslice.frame_m.second + gslice.margin_m.second);
    guide_set_t& forward_guide_set(
        container_guide_set_m[select][layout_attributes_t::align_forward]);
    guide_set_t& reverse_guide_set(
        container_guide_set_m[select][layout_attributes_t::align_reverse]);

    // Solve for guides

    for (::child_iterator iter(first); iter != last; ++iter) {
        const layout_attributes_t::slice_t& iter_gslice(iter->geometry_m.slice_m[select]);

        if (iter_gslice.suppress_m)
            continue;

        int forward_iter_length(near_additional);
        int reverse_iter_length(far_additional);

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
            forward_iter_length += iter->geometry_m.indent_m;
            break;
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
            reverse_iter_length += iter->geometry_m.indent_m;
            break;
        default:
            break;
        }

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
        case layout_attributes_t::align_reverse_fill: {
            guide_set_t& forward_child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

            for (guide_set_t::iterator guide_first(forward_child_guide_set.begin()),
                 guide_last(forward_child_guide_set.end()), base_guide(forward_guide_set.begin());
                 guide_first != guide_last; ++guide_first, ++base_guide) {
                assert(base_guide != forward_guide_set.end());
                *base_guide = std::max(*base_guide, *guide_first + forward_iter_length);
            }
        } break;
        default:
            break;
        }

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
        case layout_attributes_t::align_forward_fill: {
            guide_set_t& reverse_child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_reverse]);

            for (guide_set_t::iterator guide_first(reverse_child_guide_set.begin()),
                 guide_last(reverse_child_guide_set.end()), base_guide(reverse_guide_set.begin());
                 guide_first != guide_last; ++guide_first, ++base_guide) {
                assert(base_guide != reverse_guide_set.end());
                *base_guide = std::max(*base_guide, *guide_first + reverse_iter_length);
            }
        } break;
        default:
            break;
        }
    }

    int length(near_additional + far_additional);

    /*
    Solve for length. For containers the effects of guides needs to be solved down then back up.
    For leaf-nodes we offset them directly.
    */

    for (::child_iterator iter(first); iter != last; ++iter) {
        const layout_attributes_t::slice_t& iter_gslice(iter->geometry_m.slice_m[select]);

        int forward_iter_length(near_additional);
        int reverse_iter_length(far_additional);

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_fill:
        case layout_attributes_t::align_forward:
            forward_iter_length += iter->geometry_m.indent_m;
            break;
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
            reverse_iter_length += iter->geometry_m.indent_m;
            break;
        default:
            break;
        }

        if (iter->geometry_m.placement_m == eve_t::place_leaf && !iter_gslice.suppress_m) {
            switch (iter_gslice.alignment_m) {
            case layout_attributes_t::align_forward:
            case layout_attributes_t::align_forward_fill:
            case layout_attributes_t::align_reverse_fill: {
                guide_set_t& forward_child_guide_set(
                    iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

                if (forward_child_guide_set.size()) {
                    forward_iter_length += forward_guide_set.front() -
                                           (forward_child_guide_set.front() + forward_iter_length);
                }
            } break;
            default:
                break;
            }
            switch (iter_gslice.alignment_m) {
            case layout_attributes_t::align_reverse:
            case layout_attributes_t::align_reverse_fill:
            case layout_attributes_t::align_forward_fill: {
                guide_set_t& reverse_child_guide_set(
                    iter->container_guide_set_m[select][layout_attributes_t::align_reverse]);
                if (reverse_child_guide_set.size()) {
                    reverse_iter_length += reverse_guide_set.front() -
                                           (reverse_child_guide_set.front() + reverse_iter_length);
                }
            } break;
            default:
                break;
            }
        }

        length = std::max(length, iter->container_length_m[select] + forward_iter_length +
                                      reverse_iter_length);
    }

    // update properties on this container.

    measured_length_m[select] = length;
    container_length_m[select] = std::max(length, container_length_m[select]);
}

/**************************************************************************************************/

bool view_proxy_t::solve_down_cross(::child_iterator first, ::child_iterator last,
                                    slice_select_t select) {
    bool result(false);
    const layout_attributes_t::slice_t& gslice(geometry_m.slice_m[select]);
    const extents_t::slice_t& eslice(geometry_m.extents_m.slice_m[select]);
    int near_additional(eslice.frame_m.first + gslice.margin_m.first);
    int far_additional(eslice.frame_m.second + gslice.margin_m.second);

    // Impose guide positions on containers.

    for (::child_iterator iter(first); iter != last; ++iter) {
        const layout_attributes_t::slice_t& iter_gslice(iter->geometry_m.slice_m[select]);

        if (iter_gslice.suppress_m)
            continue;

        guide_set_t::iterator forward_guide_iter(
            container_guide_set_m[select][layout_attributes_t::align_forward].begin());
        guide_set_t::iterator reverse_guide_iter(
            container_guide_set_m[select][layout_attributes_t::align_reverse].begin());

        // Leaf nodes are offset to the first guide.

        int length(near_additional);
        int rlength(far_additional);

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_fill:
        case layout_attributes_t::align_forward:
            length += iter->geometry_m.indent_m;
            break;
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
            rlength += iter->geometry_m.indent_m;
            break;
        default:
            break;
        }

        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_forward:
        case layout_attributes_t::align_forward_fill:
        case layout_attributes_t::align_reverse_fill: {
            guide_set_t& forward_child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_forward]);

            guide_set_t::iterator forward_guide_first(forward_child_guide_set.begin());
            guide_set_t::iterator forward_guide_last(forward_child_guide_set.end());

            if (iter->geometry_m.placement_m == adobe::eve_t::place_leaf) {
                if (forward_guide_first != forward_guide_last)
                    length = *forward_guide_iter++ - *forward_guide_first++;
            }

            for (; forward_guide_first != forward_guide_last;
                 ++forward_guide_first, ++forward_guide_iter) {
                int new_guide(*forward_guide_iter - length);
                if (new_guide != *forward_guide_first) {
                    result = true;
                    *forward_guide_first = new_guide;
                }
            }
        } break;
        default:
            break;
        }
        switch (iter_gslice.alignment_m) {
        case layout_attributes_t::align_reverse:
        case layout_attributes_t::align_reverse_fill:
        case layout_attributes_t::align_forward_fill: {
            guide_set_t& reverse_child_guide_set(
                iter->container_guide_set_m[select][layout_attributes_t::align_reverse]);

            guide_set_t::iterator reverse_guide_first(reverse_child_guide_set.begin());
            guide_set_t::iterator reverse_guide_last(reverse_child_guide_set.end());

            if (iter->geometry_m.placement_m == adobe::eve_t::place_leaf) {
                if (reverse_guide_first != reverse_guide_last)
                    rlength = *reverse_guide_iter++ - *reverse_guide_first++;
            }

            for (; reverse_guide_first != reverse_guide_last;
                 ++reverse_guide_first, ++reverse_guide_iter) {
                int new_guide(*reverse_guide_iter - rlength);
                if (new_guide != *reverse_guide_first) {
                    result = true;
                    *reverse_guide_first = new_guide;
                }
            }
        } break;
        default:
            break;
        }
    }
    return result;
}

/**************************************************************************************************/

} // namespace implementation

/**************************************************************************************************/

#if 0
#pragma mark -
#endif

/**************************************************************************************************/

#if !defined(ADOBE_NO_DOCUMENTATION)

place_data_t::slice_t::slice_t() : length_m(0), position_m(0) {}

#endif

/**************************************************************************************************/

} // namespace adobe

/**************************************************************************************************/


text:
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
// Copyright (c) 2018 Aquila Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "intro.h"
#include "ui_intro.h"

#include "guiutil.h"

#include "util.h"

#include <boost/filesystem.hpp>

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>

/* Minimum free space (in bytes) needed for data directory */
static const uint64_t GB_BYTES = 1000000000LL;
static const uint64_t BLOCK_CHAIN_SIZE = 1LL * GB_BYTES;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the check()
   function runs, the current path is requested from the associated Intro object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject
{
    Q_OBJECT

public:
    FreespaceChecker(Intro* intro);

    enum Status {
        ST_OK,
        ST_ERROR
    };

public slots:
    void check();

signals:
    void reply(int status, const QString& message, quint64 available);

private:
    Intro* intro;
};

#include "intro.moc"

FreespaceChecker::FreespaceChecker(Intro* intro)
{
    this->intro = intro;
}

void FreespaceChecker::check()
{
    namespace fs = boost::filesystem;
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage = tr("A new data directory will be created.");

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while (parentDir.has_parent_path() && !fs::exists(parentDir)) {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite loop here */
        if (parentDirOld == parentDir)
            break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if (fs::exists(dataDir)) {
            if (fs::is_directory(dataDir)) {
                QString separator = "<code>" + QDir::toNativeSeparators("/") + tr("name") + "</code>";
                replyStatus = ST_OK;
                replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator);
            } else {
                replyStatus = ST_ERROR;
                replyMessage = tr("Path already exists, and is not a directory.");
            }
        }
    } catch (fs::filesystem_error& e) {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot create data directory here.");
    }
    emit reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget* parent) : QDialog(parent),
                                ui(new Ui::Intro),
                                thread(0),
                                signalled(false)
{
    ui->setupUi(this);
    ui->sizeWarningLabel->setText(ui->sizeWarningLabel->text().arg(BLOCK_CHAIN_SIZE / GB_BYTES));
    startThread();
}

Intro::~Intro()
{
    delete ui;
    /* Ensure thread is finished before it is deleted */
    emit stopThread();
    thread->wait();
}

QString Intro::getDataDirectory()
{
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString& dataDir)
{
    ui->dataDirectory->setText(dataDir);
    if (dataDir == getDefaultDataDirectory()) {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellaqaisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellaqaisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory()
{
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

bool Intro::pickDataDirectory()
{
    namespace fs = boost::filesystem;
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if (!GetArg("-datadir", "").empty())
        return true;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if (!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", false)) {
        /* If current default data directory does not exist, let the user choose one */
        Intro intro;
        intro.setDataDirectory(dataDir);
        intro.setWindowIcon(QIcon(":icons/bitcoin"));

        while (true) {
            if (!intro.exec()) {
                /* Cancel clicked */
                return false;
            }
            dataDir = intro.getDataDirectory();
            try {
                TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir));
                break;
            } catch (fs::filesystem_error& e) {
                QMessageBox::critical(0, tr("Aqa"),
                    tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
    }
    /* Only override -datadir if different from the default, to make it possible to
     * override -datadir in the aqa.conf file in the default data directory
     * (to be consistent with aqad behavior)
     */
    if (dataDir != getDefaultDataDirectory())
        SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
    return true;
}

void Intro::setStatus(int status, const QString& message, quint64 bytesAvailable)
{
    switch (status) {
    case FreespaceChecker::ST_OK:
        ui->errorMessage->setText(message);
        ui->errorMessage->setStyleSheet("");
        break;
    case FreespaceChecker::ST_ERROR:
        ui->errorMessage->setText(tr("Error") + ": " + message);
        ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
        break;
    }
    /* Indicate number of bytes available */
    if (status == FreespaceChecker::ST_ERROR) {
        ui->freeSpace->setText("");
    } else {
        QString freeString = tr("%1 GB of free space available").arg(bytesAvailable / GB_BYTES);
        if (bytesAvailable < BLOCK_CHAIN_SIZE) {
            freeString += " " + tr("(of %1 GB needed)").arg(BLOCK_CHAIN_SIZE / GB_BYTES);
            ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
        } else {
            ui->freeSpace->setStyleSheet("");
        }
        ui->freeSpace->setText(freeString + ".");
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString& dataDirStr)
{
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellaqaisButton_clicked()
{
    QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(0, "Choose data directory", ui->dataDirectory->text()));
    if (!dir.isEmpty())
        ui->dataDirectory->setText(dir);
}

void Intro::on_dataDirDefault_clicked()
{
    setDataDirectory(getDefaultDataDirectory());
}

void Intro::on_dataDirCustom_clicked()
{
    ui->dataDirectory->setEnabled(true);
    ui->ellaqaisButton->setEnabled(true);
}

void Intro::startThread()
{
    thread = new QThread(this);
    FreespaceChecker* executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, SIGNAL(reply(int, QString, quint64)), this, SLOT(setStatus(int, QString, quint64)));
    connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
    /*  make sure executor object is deleted in its own thread */
    connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));

    thread->start();
}

void Intro::checkPath(const QString& dataDir)
{
    mutex.lock();
    pathToCheck = dataDir;
    if (!signalled) {
        signalled = true;
        emit requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck()
{
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}

ext: cpp


text:
//此源码被清华学神尹成大魔王专业翻译分析并修改
//尹成QQ77025077
//尹成微信18510341407
//尹成所在QQ群721929980
//尹成邮箱 yinc13@mails.tsinghua.edu.cn
//尹成毕业于清华大学,微软区块链领域全球最有价值专家
//https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
//————————————————————————————————————————————————————————————————————————————————————————————————————————————————
/*
    此文件是Rippled的一部分：https://github.com/ripple/rippled
    版权所有（c）2012-2015 Ripple Labs Inc.

    使用、复制、修改和/或分发本软件的权限
    特此授予免费或不收费的目的，前提是
    版权声明和本许可声明出现在所有副本中。

    本软件按“原样”提供，作者不作任何保证。
    关于本软件，包括
    适销性和适用性。在任何情况下，作者都不对
    任何特殊、直接、间接或后果性损害或任何损害
    因使用、数据或利润损失而导致的任何情况，无论是在
    合同行为、疏忽或其他侵权行为
    或与本软件的使用或性能有关。
**/

//==============================================================

#include <ripple/basics/mulDiv.h>
#include <ripple/basics/contract.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <limits>
#include <utility>

namespace ripple
{

std::pair<bool, std::uint64_t>
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
    using namespace boost::multiprecision;

    uint128_t result;
    result = multiply(result, value, mul);

    result /= div;

    auto const limit = std::numeric_limits<std::uint64_t>::max();

    if (result > limit)
        return { false, limit };

    return { true, static_cast<std::uint64_t>(result) };
}

} //涟漪

max_stars_repo_name: yinchengtsinghua/RippleCPPChinese

max_issues_repo_name: yinchengtsinghua/RippleCPPChinese

max_forks_repo_name: yinchengtsinghua/RippleCPPChinese


text:
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <Eigen/SVD>
#include <Eigen/LU>

template<typename MatrixType> void svd(const MatrixType& m)
{
  /* this test covers the following files:
     SVD.h
  */
  typename MatrixType::Index rows = m.rows();
  typename MatrixType::Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  MatrixType a = MatrixType::Random(rows,cols);
  Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> b =
    Matrix<Scalar, MatrixType::RowsAtCompileTime, 1>::Random(rows,1);
  Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> x(cols,1), x2(cols,1);

  {
    SVD<MatrixType> svd(a);
    MatrixType sigma = MatrixType::Zero(rows,cols);
    MatrixType matU  = MatrixType::Zero(rows,rows);
    sigma.diagonal() = svd.singularValues();
    matU = svd.matrixU();
    VERIFY_IS_APPROX(a, matU * sigma * svd.matrixV().transpose());
  }

  if (rows==cols)
  {
    if (ei_is_same_type<RealScalar,float>::ret)
    {
      MatrixType a1 = MatrixType::Random(rows,cols);
      a += a * a.adjoint() + a1 * a1.adjoint();
    }
    SVD<MatrixType> svd(a);
    x = svd.solve(b);
    VERIFY_IS_APPROX(a * x,b);
  }

  if(rows==cols)
  {
    SVD<MatrixType> svd(a);
    MatrixType unitary, positive;
    svd.computeUnitaryPositive(&unitary, &positive);
    VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
    VERIFY_IS_APPROX(positive, positive.adjoint());
    for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
    VERIFY_IS_APPROX(unitary*positive, a);

    svd.computePositiveUnitary(&positive, &unitary);
    VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
    VERIFY_IS_APPROX(positive, positive.adjoint());
    for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
    VERIFY_IS_APPROX(positive*unitary, a);
  }
}

template<typename MatrixType> void svd_verify_assert()
{
  MatrixType tmp;

  SVD<MatrixType> svd;
  VERIFY_RAISES_ASSERT(svd.solve(tmp))
  VERIFY_RAISES_ASSERT(svd.matrixU())
  VERIFY_RAISES_ASSERT(svd.singularValues())
  VERIFY_RAISES_ASSERT(svd.matrixV())
  VERIFY_RAISES_ASSERT(svd.computeUnitaryPositive(&tmp,&tmp))
  VERIFY_RAISES_ASSERT(svd.computePositiveUnitary(&tmp,&tmp))
  VERIFY_RAISES_ASSERT(svd.computeRotationScaling(&tmp,&tmp))
  VERIFY_RAISES_ASSERT(svd.computeScalingRotation(&tmp,&tmp))
}

void test_svd()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( svd(Matrix3f()) );
    CALL_SUBTEST_2( svd(Matrix4d()) );
    CALL_SUBTEST_3( svd(MatrixXf(7,7)) );
    CALL_SUBTEST_4( svd(MatrixXd(14,7)) );
    // complex are not implemented yet
//     CALL_SUBTEST(svd(MatrixXcd(6,6)) );
//     CALL_SUBTEST(svd(MatrixXcf(3,3)) );
  }

  CALL_SUBTEST_1( svd_verify_assert<Matrix3f>() );
  CALL_SUBTEST_2( svd_verify_assert<Matrix4d>() );
  CALL_SUBTEST_3( svd_verify_assert<MatrixXf>() );
  CALL_SUBTEST_4( svd_verify_assert<MatrixXd>() );

  // Test problem size constructors
  CALL_SUBTEST_9( SVD<MatrixXf>(10, 20) );
}


text: #include <boost/random/fisher_f_distribution.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/json
//

#ifndef BOOST_JSON_MEMORY_RESOURCE_HPP
#define BOOST_JSON_MEMORY_RESOURCE_HPP

#include <boost/json/detail/config.hpp>
#ifndef BOOST_JSON_STANDALONE
# include <boost/container/pmr/memory_resource.hpp>
# include <boost/container/pmr/polymorphic_allocator.hpp>
#else
# if __has_include(<memory_resource>)
#  include <memory_resource>
//#  if __cpp_lib_memory_resource < 201603L
#  ifndef __cpp_lib_memory_resource
#   error Support for std::memory_resource is required to use Boost.JSON standalone
#  endif
# else
#  error Header <memory_resource> is required to use Boost.JSON standalone
# endif
#endif

BOOST_JSON_NS_BEGIN

#ifdef BOOST_JSON_DOCS

/** The type of memory resource used by the library.

    This type alias is set depending
    on how the library is configured:

    @par Use with Boost

    If the macro `BOOST_JSON_STANDALONE` is
    not defined, this type will be an alias
    for `boost::container::pmr::memory_resource`.
    Compiling a program using the library will
    require Boost, and a compiler conforming
    to C++11 or later.

    @par Use without Boost

    If the macro `BOOST_JSON_STANDALONE` is
    defined, this type will be an alias
    for `std::pmr::memory_resource`.
    Compiling a program using the library will
    require only a compiler conforming to C++17
    or later.

    @see https://en.cppreference.com/w/cpp/memory/memory_resource
*/
class memory_resource
{
};

/** The type of polymorphic allocator used by the library.

    This type alias is set depending
    on how the library is configured:

    @par Use with Boost

    If the macro `BOOST_JSON_STANDALONE` is
    not defined, this type will be an alias template
    for `boost::container::pmr::polymorphic_allocator`.
    Compiling a program using the library will
    require Boost, and a compiler conforming
    to C++11 or later.

    @par Use without Boost

    If the macro `BOOST_JSON_STANDALONE` is
    defined, this type will be an alias template
    for `std::pmr::polymorphic_allocator`.
    Compiling a program using the library will
    require only a compiler conforming to C++17
    or later.

    @see https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
*/
template<class T>
class polymorphic_allocator;

// VFALCO Bug: doc toolchain won't make this a ref
//using memory_resource = __see_below__;

#elif ! defined(BOOST_JSON_STANDALONE)

using memory_resource = boost::container::pmr::memory_resource;

template<class T>
using polymorphic_allocator =
    boost::container::pmr::polymorphic_allocator<T>;

#else

using memory_resource = std::pmr::memory_resource;
template<class T>
using polymorphic_allocator =
    std::pmr::polymorphic_allocator<T>;

#endif

/** Return true if a memory resource's deallocate function has no effect.

    This metafunction may be specialized to indicate to
    the library that calls to the `deallocate` function of
    a @ref memory_resource have no effect. The implementation
    will elide such calls when it is safe to do so. By default,
    the implementation assumes that all memory resources
    require a call to `deallocate` for each memory region
    obtained by calling `allocate`.

    @par Example

    This example specializes the metafuction for `my_resource`,
    to indicate that calls to deallocate have no effect:

    @code

    // Forward-declaration for a user-defined memory resource
    struct my_resource;

    // It is necessary to specialize the template from
    // inside the namespace in which it is declared:

    namespace boost {
    namespace json {

    template<>
    struct is_deallocate_trivial< my_resource >
    {
        static constexpr bool value = true;
    };

    } // namespace json
    } // namespace boost

    @endcode

    It is usually not necessary for users to check this trait.
    Instead, they can call @ref storage_ptr::is_deallocate_trivial
    to determine if the pointed-to memory resource has a trivial
    deallocate function.

    @see
        @ref memory_resource,
        @ref storage_ptr
*/
template<class T>
struct is_deallocate_trivial
{
    /** A bool equal to true if calls to `T::do_deallocate` have no effect.

        The primary template sets `value` to false.
    */
    static constexpr bool value = false;
};

BOOST_JSON_NS_END

#endif

max_stars_repo_name: Julien-Blanc-tgcm/json

max_issues_repo_name: Julien-Blanc-tgcm/json

max_forks_repo_name: Julien-Blanc-tgcm/json


text:
//****************************************************************************
// (c) 2008, 2009 by the openOR Team
//****************************************************************************
// The contents of this file are available under the GPL v2.0 license
// or under the openOR comercial license. see
//   /Doc/openOR_free_license.txt or
//   /Doc/openOR_comercial_license.txt
// for Details.
//****************************************************************************
//! OPENOR_INTERFACE_FILE(Image_ImageData)
//****************************************************************************
/**
 * @file
 * @author Christian Winne
 * \ingroup Image_ImageData
 */

#ifndef openOR_Image_Image1DSize_hpp
#define openOR_Image_Image1DSize_hpp

#include <boost/tr1/memory.hpp>

#include <openOR/Plugin/CreateInterface.hpp> //openOr_core
#include <openOR/Math/vector.hpp>//openOr_core
#include <openOR/Math/matrix.hpp> //openOR_core
#include <openOR/Utility/Types.hpp> //openOr_core

namespace openOR {
   namespace Image {

      /**
       * \brief Interface that describes the size of an 1D image.
       * The image is described by its pixel count and its size in millimeter.
       * \ingroup Image_ImageData
       */
      struct Image1DSize
      {
         virtual unsigned int size() const = 0;
         virtual void setSize(const unsigned int& size) = 0;

         virtual double sizeMM() const = 0;
         virtual void setSizeMM(const double& sizeMM) = 0;

      };

   }

   /*
    * Getter for the voxel width in mm
    * @return The voxel width in mm
    */
   inline const double pixelWidthMM(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize) { return pImageSize->sizeMM() / pImageSize->size(); }

   inline const double pixelSizeMM(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize)
   {
      return pixelWidthMM(pImageSize);
   }

   /**
    * Getter for the width of the whole volume object in mm
    * @return The width of the volume object
    */
   inline const double getMMWidth(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize) { return pImageSize->sizeMM(); }

   inline const double getMMSize(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize) { return pImageSize->sizeMM(); }

   /**
    * Getter for the width of the whole volume object in indices
    * @return The width of the volume object
    */
   inline const uint getWidth(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize) { return pImageSize->size(); }

   /**
    * Getter for the depth of the whole volume object in indices
    * @return The depth of the volume object
    */
   inline const double getSize(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize) { return pImageSize->size(); }

   // /**
    // * Checks whether given relative mm-based point is outside of volume
    // * @param  vecPoint The point to check for
    // * @return  True, if the point is outside the volume
    // */
   // inline const bool isOutside(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize, const Math::Vector2d& vecPoint) { assert(true); return true; }

  // /**
   // * Checks whether given relative index-based point is outside of volume
   // * @param vecPoint The point to check for
   // * @return  True, if the point is outside the volume
   // */
  // inline const bool isOutside(std::tr1::shared_ptr<const Image::Image2DSize> pImageSize, const Math::Vector2i& vecPoint) { assert(true); return true; }

  // /**
   // * Returns the absolute BoundingBox around the volume.
   // * @return   The absolute BoundingBox around the volume
   // */
  // //Math::BoundingBoxD getBoundingBox(std::tr1::shared_ptr<const Volume> pVolume) {}

   /**
    * Returns index position corresponding to the given mm position.
    * @return The index position
    */
  inline const unsigned int convertToIndex(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize, const unsigned int& pos)
  {
    return pos;
  }

  inline const unsigned int convertToIndex(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize, const int& pos)
  {
    assert(pos >= 0 && pos < static_cast<int>(pImageSize->size()));

    unsigned int vec = static_cast<uint>(pos);
    return convertToIndex(pImageSize, vec);
  }

  inline const int convertToIndexPosition(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize, const double& posMM)
  {
    return static_cast<int>(posMM * pImageSize->size() / pImageSize->sizeMM());
  }

  /**
   * Returns internal memory index corresponding to the given index/mm position.
   * @return The index
   */
  inline const unsigned int convertToIndex(std::tr1::shared_ptr<const Image::Image1DSize> pImageSize, const double& posMM)
  {
    return convertToIndex(pImageSize, convertToIndexPosition(pImageSize, posMM));
  }

}

OPENOR_CREATE_INTERFACE(openOR::Image::Image1DSize)
double sizeMM() const { return adaptee()->sizeMM(); }
void setSizeMM(const double& size) { adaptee()->setSizeMM(size); }
unsigned int size() const { return adaptee()->size(); }
void setSize(const unsigned int& size) { adaptee()->setSize(size); }
OPENOR_CREATE_INTERFACE_END

#endif

max_stars_repo_name: avinfinity/UnmanagedCodeSnippets

max_issues_repo_name: avinfinity/UnmanagedCodeSnippets

max_forks_repo_name: avinfinity/UnmanagedCodeSnippets