klayout/src/laybasic/layLayerProperties.cc

2014 lines
55 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2017 Matthias Koefferlein
This program is free software; 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.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layLayerProperties.h"
#include "layLayoutView.h"
#include "layConverters.h"
#include "tlXMLParser.h"
#include "tlException.h"
#include "tlExpression.h"
#include "tlAssert.h"
#include <algorithm>
namespace lay
{
// -------------------------------------------------------------
// LayerProperties implementation
/**
* @brief The brightness correction
*
* The brightness is a logarithmic scaling of the rgb values
* towards black (x < 0) or white (x > 0). A brightness correction
* of 128 reduces the intensity (in case of correction to black)
* by a factor of 2, a correction of 256 by a factor of 4.
* All channels are scaled the same way in order not to change the
* color but the brightness alone.
*/
color_t
LayerProperties::brighter (color_t in, int x)
{
// shortcut for no correction
if (x == 0) {
return in;
}
int r = (in >> 16) & 0xff;
int g = (in >> 8) & 0xff;
int b = in & 0xff;
static double f = log (2.0) / 128.0;
if (x < 0) {
x = int (256.0 * exp (f * x) + 0.5);
r = (x * r) / 256;
g = (x * g) / 256;
b = (x * b) / 256;
} else {
x = int (256.0 * exp (f * -x) + 0.5);
r = 255 - (x * (255 - r)) / 256;
g = 255 - (x * (255 - g)) / 256;
b = 255 - (x * (255 - b)) / 256;
}
return (r << 16) + (g << 8) + b;
}
LayerProperties::LayerProperties ()
: m_frame_color (0),
m_frame_color_real (0),
m_fill_color (0),
m_fill_color_real (0),
m_frame_brightness (0),
m_frame_brightness_real (0),
m_fill_brightness (0),
m_fill_brightness_real (0),
m_dither_pattern (-1),
m_dither_pattern_real (-1),
m_line_style (-1),
m_line_style_real (-1),
m_valid (true),
m_valid_real (true),
m_visible (true),
m_visible_real (true),
m_transparent (false),
m_transparent_real (false),
m_width (-1),
m_width_real (-1),
m_marked (false),
m_marked_real (false),
m_xfill (false),
m_xfill_real (false),
m_animation (0),
m_animation_real (0),
m_source (),
m_source_real (),
m_layer_index (-1),
m_cellview_index (-1),
m_inv_prop_set (false),
m_realize_needed_source (true),
m_realize_needed_visual (true)
{
// .. nothing yet ..
}
LayerProperties::LayerProperties (const LayerProperties &d)
: gsi::ObjectBase (d),
m_frame_color (0),
m_frame_color_real (0),
m_fill_color (0),
m_fill_color_real (0),
m_frame_brightness (0),
m_frame_brightness_real (0),
m_fill_brightness (0),
m_fill_brightness_real (0),
m_dither_pattern (-1),
m_dither_pattern_real (-1),
m_line_style (-1),
m_line_style_real (-1),
m_valid (true),
m_valid_real (true),
m_visible (true),
m_visible_real (true),
m_transparent (false),
m_transparent_real (false),
m_width (-1),
m_width_real (-1),
m_marked (false),
m_marked_real (false),
m_xfill (false),
m_xfill_real (false),
m_animation (0),
m_animation_real (0),
m_source (),
m_source_real (),
m_layer_index (-1),
m_cellview_index (-1),
m_inv_prop_set (false),
m_realize_needed_source (true),
m_realize_needed_visual (true)
{
operator= (d);
}
LayerProperties &
LayerProperties::operator= (const LayerProperties &d)
{
if (&d != this) {
d.ensure_realized ();
int flags = 0;
if (m_frame_color != d.m_frame_color ||
m_fill_color != d.m_fill_color ||
m_frame_brightness != d.m_frame_brightness ||
m_fill_brightness != d.m_fill_brightness ||
m_dither_pattern != d.m_dither_pattern ||
m_line_style != d.m_line_style ||
m_valid != d.m_valid ||
m_visible != d.m_visible ||
m_transparent != d.m_transparent ||
m_width != d.m_width ||
m_marked != d.m_marked ||
m_xfill != d.m_xfill ||
m_animation != d.m_animation) {
m_frame_color = d.m_frame_color;
m_fill_color = d.m_fill_color;
m_frame_brightness = d.m_frame_brightness;
m_fill_brightness = d.m_fill_brightness;
m_dither_pattern = d.m_dither_pattern;
m_line_style = d.m_line_style;
m_valid = d.m_valid;
m_visible = d.m_visible;
m_transparent = d.m_transparent;
m_width = d.m_width;
m_marked = d.m_marked;
m_xfill = d.m_xfill;
m_animation = d.m_animation;
flags += nr_visual;
}
if (m_source != d.m_source) {
m_source = d.m_source;
flags += nr_source;
}
if (flags) {
need_realize (flags, true /*force on children*/);
}
m_name = d.m_name;
}
return *this;
}
LayerProperties::~LayerProperties ()
{
// .. nothing yet ..
}
bool
LayerProperties::operator== (const LayerProperties &d) const
{
ensure_realized ();
d.ensure_realized ();
// do not consider the derived and "real" properties - these is not really a property
return m_frame_color == d.m_frame_color &&
m_fill_color == d.m_fill_color &&
m_frame_brightness == d.m_frame_brightness &&
m_fill_brightness == d.m_fill_brightness &&
m_dither_pattern == d.m_dither_pattern &&
m_line_style == d.m_line_style &&
m_valid == d.m_valid &&
m_visible == d.m_visible &&
m_transparent == d.m_transparent &&
m_width == d.m_width &&
m_marked == d.m_marked &&
m_xfill == d.m_xfill &&
m_animation == d.m_animation &&
m_name == d.m_name &&
m_source == d.m_source;
}
bool
LayerProperties::is_visual () const
{
return valid (true) && visible (true) && (layer_index () >= 0 || is_cell_box_layer ());
}
color_t
LayerProperties::eff_frame_color (bool real) const
{
return brighter (frame_color (real) & 0xffffff, frame_brightness (real));
}
color_t
LayerProperties::eff_fill_color (bool real) const
{
return brighter (fill_color (real) & 0xffffff, fill_brightness (real));
}
color_t
LayerProperties::eff_frame_color_brighter (bool real, int plus_brightness) const
{
return brighter (frame_color (real) & 0xffffff, frame_brightness (real) + plus_brightness);
}
color_t
LayerProperties::eff_fill_color_brighter (bool real, int plus_brightness) const
{
return brighter (fill_color (real) & 0xffffff, fill_brightness (real) + plus_brightness);
}
void
LayerProperties::merge_visual (const LayerProperties *d) const
{
if (!d || !d->has_frame_color (true)) {
m_frame_color_real = m_frame_color;
} else {
m_frame_color_real = d->m_frame_color;
}
if (!d || !d->has_fill_color (true)) {
m_fill_color_real = m_fill_color;
} else {
m_fill_color_real = d->m_fill_color;
}
m_frame_brightness_real = m_frame_brightness;
if (d) {
m_frame_brightness_real += d->m_frame_brightness_real;
}
m_fill_brightness_real = m_fill_brightness;
if (d) {
m_fill_brightness_real += d->m_fill_brightness_real;
}
if (!d || !d->has_dither_pattern (true)) {
m_dither_pattern_real = m_dither_pattern;
} else {
m_dither_pattern_real = d->m_dither_pattern_real;
}
if (!d || !d->has_line_style (true)) {
m_line_style_real = m_line_style;
} else {
m_line_style_real = d->m_line_style_real;
}
m_valid_real = m_valid && (!d || d->m_valid_real);
m_visible_real = m_visible && (!d || d->m_visible_real);
m_xfill_real = m_xfill && (!d || d->m_xfill_real);
m_transparent_real = m_transparent || (d && d->m_transparent_real);
m_marked_real = m_marked || (d && d->m_marked_real);
m_width_real = m_width;
if (d && d->m_width_real > m_width) {
m_width_real = d->m_width_real;
}
m_animation_real = m_animation;
if (d && m_animation_real == 0) {
m_animation_real = d->m_animation_real;
}
}
void
LayerProperties::merge_source (const LayerProperties *d) const
{
m_source_real = m_source;
if (d) {
m_source_real += d->m_source_real;
}
}
void
LayerProperties::ensure_realized () const
{
ensure_source_realized ();
ensure_visual_realized ();
}
void
LayerProperties::ensure_source_realized () const
{
if (m_realize_needed_source) {
realize_source ();
m_realize_needed_source = false;
}
}
void
LayerProperties::ensure_visual_realized () const
{
if (m_realize_needed_visual) {
realize_visual ();
m_realize_needed_visual = false;
}
}
LayerProperties
LayerProperties::flat () const
{
ensure_realized ();
// initialize the result object with the "real" properties
LayerProperties r;
r.m_frame_color = r.m_frame_color_real = m_frame_color_real;
r.m_fill_color = r.m_fill_color_real = m_fill_color_real;
r.m_frame_brightness = r.m_frame_brightness_real = m_frame_brightness_real;
r.m_fill_brightness = r.m_fill_brightness_real = m_fill_brightness_real;
r.m_dither_pattern = r.m_dither_pattern_real = m_dither_pattern_real;
r.m_line_style = r.m_line_style_real = m_line_style_real;
r.m_valid = r.m_valid_real = m_valid_real;
r.m_visible = r.m_visible_real = m_visible_real;
r.m_transparent = r.m_transparent_real = m_transparent_real;
r.m_width = r.m_width_real = m_width_real;
r.m_marked = r.m_marked_real = m_marked_real;
r.m_xfill = r.m_xfill_real = m_xfill_real;
r.m_animation = r.m_animation_real = m_animation_real;
r.m_name = m_name;
r.m_source = r.m_source_real = m_source_real;
r.m_layer_index = m_layer_index;
r.m_cellview_index = m_cellview_index;
r.m_trans = m_trans;
r.m_hier_levels = m_hier_levels;
r.m_prop_set = m_prop_set;
r.m_inv_prop_set = m_inv_prop_set;
r.m_realize_needed_source = r.m_realize_needed_visual = false;
return r;
}
class LayerSourceEval
: public tl::Eval
{
public:
LayerSourceEval (const lay::LayerProperties &lp, const lay::LayoutView *view, bool real)
: m_lp (lp), mp_view (view), m_real (real)
{
// .. nothing yet ..
}
const lay::ParsedLayerSource &source () const
{
return m_lp.source (m_real);
}
const lay::LayoutView *view () const
{
return mp_view;
}
private:
const lay::LayerProperties &m_lp;
const lay::LayoutView *mp_view;
bool m_real;
};
class LayerSourceEvalFunction
: public tl::EvalFunction
{
public:
LayerSourceEvalFunction (char function, const LayerSourceEval *eval)
: m_function (function), mp_eval (eval)
{
// .. nothing yet ..
}
void execute (const tl::ExpressionParserContext &context, tl::Variant &out, const std::vector <tl::Variant> &vv) const
{
if (vv.size () != 0) {
throw tl::EvalError (tl::to_string (QObject::tr ("Layer source function must not have arguments")), context);
}
out = tl::Variant ();
if (m_function == 'N') {
if (mp_eval->source ().has_name ()) {
out = mp_eval->source ().name ();
}
} else if (m_function == 'L') {
if (mp_eval->source ().layer () >= 0) {
out = mp_eval->source ().layer ();
}
} else if (m_function == 'D') {
if (mp_eval->source ().datatype () >= 0) {
out = mp_eval->source ().datatype ();
}
} else if (m_function == 'I') {
if (mp_eval->source ().layer_index () >= 0) {
out = mp_eval->source ().layer_index ();
}
} else if (m_function == 'C') {
if (mp_eval->source ().cv_index () >= 0) {
out = mp_eval->source ().cv_index ();
}
} else if (m_function == 'S') {
out = mp_eval->source ().display_string (mp_eval->view ());
} else if (m_function == 'T') {
const lay::CellView &cv = mp_eval->view ()->cellview (mp_eval->source ().cv_index ());
if (cv.is_valid ()) {
out = cv->name ();
}
}
}
private:
char m_function;
const LayerSourceEval *mp_eval;
};
std::string
LayerProperties::display_string (const lay::LayoutView *view, bool real, bool always_show_source) const
{
try {
std::string ret;
if (! m_name.empty ()) {
if (m_name.find ("$") == std::string::npos) {
ret = m_name;
} else {
if (m_realize_needed_source) {
realize_source ();
}
LayerSourceEval eval (*this, view, real);
eval.define_function ("N", new LayerSourceEvalFunction ('N', &eval)); // layer name
eval.define_function ("L", new LayerSourceEvalFunction ('L', &eval)); // layer number
eval.define_function ("D", new LayerSourceEvalFunction ('D', &eval)); // datatype
eval.define_function ("I", new LayerSourceEvalFunction ('I', &eval)); // layer index
eval.define_function ("C", new LayerSourceEvalFunction ('C', &eval)); // cv index
eval.define_function ("S", new LayerSourceEvalFunction ('S', &eval)); // layer source
eval.define_function ("T", new LayerSourceEvalFunction ('T', &eval)); // title
ret = eval.interpolate (m_name);
}
if (always_show_source || view->always_show_source ()) {
ret += " - ";
ret += source (real).display_string (view);
}
} else {
ret = source (real).display_string (view);
}
return ret;
} catch (tl::Exception &ex) {
return ex.msg ();
}
}
void
LayerProperties::set_xfill (bool xf)
{
if (xf != m_xfill) {
m_xfill = xf;
need_realize (nr_visual);
}
}
void
LayerProperties::set_source (const std::string &s)
{
set_source (lay::ParsedLayerSource (s));
}
void
LayerProperties::set_source (const lay::ParsedLayerSource &s)
{
if (m_source != s) {
m_source = s;
need_realize (nr_source);
}
}
void
LayerProperties::realize_visual () const
{
// do as much as we can. The node implementation will provide a
// parent and a view if possible.
merge_visual (0);
}
void
LayerProperties::realize_source () const
{
// do as much as we can. The node implementation will provide a
// parent and a view if possible.
merge_source (0);
do_realize (0);
}
void
LayerProperties::need_realize (unsigned int flags, bool /*force*/)
{
if ((flags & nr_source) != 0) {
m_realize_needed_source = true;
}
if ((flags & nr_visual) != 0) {
m_realize_needed_visual = true;
}
}
void
LayerProperties::do_realize (const LayoutView *view) const
{
m_layer_index = -1;
m_cellview_index = -1;
m_trans.clear ();
m_inv_prop_set = true;
m_prop_set.clear ();
m_hier_levels = m_source_real.hier_levels ();
if (view) {
if (m_source_real.cv_index () < 0) {
if (view->cellviews () > 0) {
m_cellview_index = 0;
}
} else if (m_source_real.cv_index () < int (view->cellviews ())) {
m_cellview_index = m_source_real.cv_index ();
}
if (m_cellview_index >= 0) {
const lay::CellView &cv = view->cellview (m_cellview_index);
// retrieve the property selector, if one is present
if (! m_source_real.property_selector ().is_null ()) {
m_inv_prop_set = m_source_real.property_selector ().matching (cv->layout ().properties_repository (), m_prop_set);
}
// compute the effective transformation in database units
m_trans = m_source_real.trans ();
if (m_source_real.special_purpose () == ParsedLayerSource::SP_None) {
m_layer_index = m_source_real.layer_index ();
// lookup the layer with the given name/layer/datatype
if (m_layer_index < 0 && ! m_source_real.is_wildcard_layer ()) {
for (unsigned int i = 0; i < cv->layout ().layers () && m_layer_index < 0; ++i) {
if (cv->layout ().is_valid_layer (i) && m_source_real.match (cv->layout ().get_properties (i))) {
m_layer_index = int (i);
}
}
}
}
}
}
if (m_trans.empty ()) {
m_trans.push_back (db::DCplxTrans ());
}
}
// -------------------------------------------------------------
// LayerPropertiesNode implementation
static unsigned int s_unique_id = 0;
LayerPropertiesNode::LayerPropertiesNode ()
: LayerProperties (),
m_list_index (0)
{
m_id = ++s_unique_id;
}
LayerPropertiesNode::~LayerPropertiesNode ()
{
// .. nothing yet ..
}
LayerPropertiesNode::LayerPropertiesNode (const LayerProperties &d)
: LayerProperties (d),
m_list_index (0)
{
m_id = ++s_unique_id;
}
LayerPropertiesNode::LayerPropertiesNode (const LayerPropertiesNode &d)
: LayerProperties (d), tl::Object (),
m_list_index (0),
m_children (d.m_children),
m_id (d.m_id)
{
for (iterator c = begin_children (); c != end_children (); ++c) {
c->set_parent (this);
}
}
LayerPropertiesNode &
LayerPropertiesNode::operator= (const LayerPropertiesNode &d)
{
if (&d != this) {
m_children = d.m_children;
m_id = d.m_id;
for (iterator c = begin_children (); c != end_children (); ++c) {
c->set_parent (this);
}
LayerProperties::operator= (d);
need_realize (nr_hierarchy, true);
}
return *this;
}
bool
LayerPropertiesNode::operator== (const LayerPropertiesNode &d) const
{
if (! LayerProperties::operator== (d)) {
return false;
}
return m_children == d.m_children;
}
LayoutView *
LayerPropertiesNode::view () const
{
return const_cast<lay::LayoutView *> (mp_view.get ());
}
unsigned int
LayerPropertiesNode::list_index () const
{
return m_list_index;
}
void
LayerPropertiesNode::realize_visual () const
{
// make sure the parents are realized
if (mp_parent && mp_parent->realize_needed_visual ()) {
mp_parent->realize_visual ();
}
merge_visual (mp_parent.get ());
}
void
LayerPropertiesNode::realize_source () const
{
// make sure the parents are realized
if (mp_parent && mp_parent->realize_needed_source ()) {
mp_parent->realize_source ();
}
merge_source (mp_parent.get ());
do_realize (mp_view.get ());
}
void
LayerPropertiesNode::need_realize (unsigned int flags, bool force)
{
if ((flags & (nr_visual + nr_source)) != 0 && (force || ! realize_needed_visual () || ! realize_needed_source ())) {
LayerProperties::need_realize (flags);
for (iterator c = begin_children (); c != end_children (); ++c) {
c->need_realize (flags, force);
}
}
}
void
LayerPropertiesNode::set_parent (const LayerPropertiesNode *parent)
{
mp_parent.reset (const_cast<LayerPropertiesNode *>(parent));
}
db::DBox
LayerPropertiesNode::bbox () const
{
tl_assert (mp_view);
lay::CellView cv = mp_view->cellview (cellview_index ());
if (! cv.is_valid ()) {
return db::DBox ();
} else if (is_cell_box_layer ()) {
db::DBox b;
double dbu = cv->layout ().dbu ();
for (std::vector<db::DCplxTrans>::const_iterator t = trans ().begin (); t != trans ().end (); ++t) {
b += (*t * db::CplxTrans (dbu) * cv.context_trans ()) * cv.cell ()->bbox ();
}
return b;
} else {
db::DBox b;
double dbu = cv->layout ().dbu ();
for (std::vector<db::DCplxTrans>::const_iterator t = trans ().begin (); t != trans ().end (); ++t) {
b += (*t * db::CplxTrans (dbu) * cv.context_trans ()) * cv.cell ()->bbox (layer_index ());
}
return b;
}
}
void
LayerPropertiesNode::attach_view (LayoutView *view, unsigned int list_index)
{
mp_view.reset (view);
m_list_index = list_index;
for (iterator c = begin_children (); c != end_children (); ++c) {
c->attach_view (view, list_index);
}
// Attachment of a view is a strong indication that something significant changed -
// recompute the source specfications on next request
m_realize_needed_source = true;
}
LayerPropertiesNode &
LayerPropertiesNode::insert_child (const iterator &iter, const LayerPropertiesNode &child)
{
iterator i = m_children.insert (iter, child);
i->set_parent (this);
need_realize (nr_hierarchy, true);
return *i;
}
void
LayerPropertiesNode::erase_child (const iterator &iter)
{
m_children.erase (iter);
need_realize (nr_hierarchy, true);
}
void
LayerPropertiesNode::add_child (const LayerPropertiesNode &child)
{
m_children.push_back (child);
m_children.back ().set_parent (this);
need_realize (nr_hierarchy, true);
}
// -------------------------------------------------------------
// LayerPropertiesConstIterator implementation
LayerPropertiesConstIterator::LayerPropertiesConstIterator ()
: m_uint (0), m_list (), mp_obj (0)
{
// .. nothing yet ..
}
LayerPropertiesConstIterator::LayerPropertiesConstIterator (const lay::LayerPropertiesNode *node)
: m_uint (0), m_list (), mp_obj (0)
{
if (!node) {
return;
}
// determine the position of the layer properties in the hierarchy of nodes
std::vector<size_t> child_indexes;
while (node->parent ()) {
size_t index = 0;
bool found = false;
for (lay::LayerPropertiesNode::const_iterator c = node->parent ()->begin_children (); c != node->parent ()->end_children (); ++c, ++index) {
if (&*c == node) {
found = true;
break;
}
}
if (!found) {
return;
}
child_indexes.push_back (index);
node = node->parent ();
}
if (!node->view ()) {
return;
}
{
const lay::LayerPropertiesList &list = node->view ()->get_properties (node->list_index ());
size_t index = 0;
bool found = false;
for (lay::LayerPropertiesList::const_iterator c = list.begin_const (); c != list.end_const (); ++c, ++index) {
if (&*c == node) {
found = true;
break;
}
}
if (!found) {
return;
}
child_indexes.push_back (index);
}
// unfold the final iterator by recursing down the hierarchy path
lay::LayerPropertiesConstIterator iter = node->view()->begin_layers ();
while (!child_indexes.empty () && !iter.at_end () && !iter.is_null ()) {
iter.to_sibling (child_indexes.back ());
child_indexes.pop_back ();
if (! child_indexes.empty ()) {
iter = iter.first_child ();
}
}
*this = iter;
}
LayerPropertiesConstIterator::LayerPropertiesConstIterator (const LayerPropertiesList &list, bool last)
// NOTE: there should be some "const_weak_ptr"
: m_uint (0), m_list (const_cast<LayerPropertiesList *> (&list)), mp_obj (0)
{
if (last) {
m_uint = (list.end_const () - list.begin_const ()) + 1;
} else {
m_uint = 1;
}
}
LayerPropertiesConstIterator::LayerPropertiesConstIterator (const LayerPropertiesList &list, size_t uint)
// NOTE: there should be some "const_weak_ptr"
: m_uint (uint), m_list (const_cast<LayerPropertiesList *> (&list)), mp_obj (0)
{
// .. nothing yet ..
}
LayerPropertiesConstIterator::LayerPropertiesConstIterator (const LayerPropertiesConstIterator &d)
: tl::Object (), m_uint (d.m_uint), m_list (d.m_list), mp_obj (d.mp_obj)
{
// .. nothing yet ..
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::operator= (const LayerPropertiesConstIterator &d)
{
if (this != &d) {
m_uint = d.m_uint;
m_list = d.m_list;
mp_obj = d.mp_obj;
}
return *this;
}
bool
LayerPropertiesConstIterator::operator< (const LayerPropertiesConstIterator &d) const
{
tl_assert (m_list);
tl_assert (m_list == d.m_list);
size_t uint = m_uint;
size_t duint = d.m_uint;
if (uint == duint) {
return false;
}
if (!m_list) {
return false;
}
LayerPropertiesList::const_iterator iter = m_list->begin_const ();
size_t n = ((m_list->end_const () - m_list->begin_const ()) + 2);
while (true) {
size_t rem = uint % n;
size_t drem = duint % n;
if (rem != drem) {
return rem < drem;
}
uint /= n;
duint /= n;
if (uint == 0 || duint == 0) {
return uint < duint;
}
n = ((iter[rem - 1].end_children () - iter[rem - 1].begin_children ()) + 2);
iter = iter[rem - 1].begin_children ();
}
}
std::pair<size_t, size_t>
LayerPropertiesConstIterator::factor () const
{
tl_assert (m_list);
// with this definition, the 0 iterator can act as the "root"
if (m_uint == 0) {
return std::make_pair (size_t (1), size_t (1));
}
LayerPropertiesList::const_iterator iter = m_list->begin_const ();
size_t uint = m_uint;
size_t n = ((m_list->end_const () - m_list->begin_const ()) + 2);
size_t f = 1;
while (uint > n) {
size_t rem = uint % n;
uint /= n;
f *= n;
tl_assert (rem < n - 1 && rem > 0);
n = ((iter[rem - 1].end_children () - iter[rem - 1].begin_children ()) + 2);
iter = iter[rem - 1].begin_children ();
}
return std::make_pair (f, n);
}
bool
LayerPropertiesConstIterator::at_end () const
{
if (! m_list) {
return true;
} else {
std::pair <size_t, size_t> f = factor ();
return (m_uint / f.first == f.second - 1);
}
}
bool
LayerPropertiesConstIterator::at_top () const
{
tl_assert (m_list);
return m_uint < size_t ((m_list->end_const () - m_list->begin_const ()) + 2);
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::up ()
{
m_uint %= factor ().first;
mp_obj = 0;
return *this;
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::next_sibling (ptrdiff_t n)
{
m_uint += factor ().first * n;
mp_obj = 0;
return *this;
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::to_sibling (size_t n)
{
std::pair <size_t, size_t> f = factor ();
m_uint = (m_uint % f.first) + (1 + n) * f.first;
mp_obj = 0;
return *this;
}
size_t
LayerPropertiesConstIterator::num_siblings () const
{
std::pair <size_t, size_t> f = factor ();
return f.second - 2;
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::down_first_child ()
{
std::pair <size_t, size_t> f = factor ();
m_uint += f.first * f.second;
mp_obj = 0;
return *this;
}
LayerPropertiesConstIterator &
LayerPropertiesConstIterator::down_last_child ()
{
std::pair <size_t, size_t> f = factor ();
const LayerPropertiesNode *o = obj ();
m_uint += f.first * f.second * ((o->end_children () - o->begin_children ()) + 1);
mp_obj = 0;
return *this;
}
std::pair <const LayerPropertiesNode *, size_t>
LayerPropertiesConstIterator::parent_obj () const
{
tl_assert (m_list);
size_t uint = m_uint;
LayerPropertiesList::const_iterator iter = m_list->begin_const ();
size_t n = ((m_list->end_const () - m_list->begin_const ()) + 2);
size_t f = 1;
const LayerPropertiesNode *ret = 0;
while (uint > n) {
size_t rem = uint % n;
tl_assert (rem > 0);
tl_assert (rem < n - 1);
ret = &iter[rem - 1];
uint /= n;
f *= n;
n = ((ret->end_children () - ret->begin_children ()) + 2);
iter = ret->begin_children ();
}
tl_assert (uint > 0);
return std::make_pair (ret, uint - 1);
}
void
LayerPropertiesConstIterator::invalidate ()
{
mp_obj = 0;
// the iterator may be parked at a position behind the last element.
// Move one step further in this case.
std::pair <size_t, size_t> f = factor ();
if (m_uint / f.first >= f.second - 1 && !at_top ()) {
up ();
inc (1);
}
}
void
LayerPropertiesConstIterator::set_obj () const
{
if (is_null () || !m_list) {
mp_obj = 0;
} else {
tl_assert (m_list);
size_t uint = m_uint;
LayerPropertiesList::const_iterator iter = m_list->begin_const ();
size_t n = ((m_list->end_const () - m_list->begin_const ()) + 2);
size_t f = 1;
while (uint > n) {
size_t rem = uint % n;
tl_assert (rem > 0);
tl_assert (rem < n - 1);
uint /= n;
f *= n;
n = ((iter[rem - 1].end_children () - iter[rem - 1].begin_children ()) + 2);
iter = iter[rem - 1].begin_children ();
}
mp_obj = &iter[uint - 1];
}
}
void
LayerPropertiesConstIterator::inc (unsigned int d)
{
if (d == 0) {
return;
} else if (d == 1) {
if (obj ()->has_children ()) {
down_first_child ();
} else {
while (true) {
std::pair <size_t, size_t> f = factor ();
m_uint += f.first;
mp_obj = 0;
if (m_uint / f.first < f.second - 1) {
break;
} else if (at_top ()) {
break;
} else {
up ();
}
}
}
} else {
// :KLUDGE: this is pretty slow ..
while (d-- > 0) {
inc (1);
}
}
}
size_t
LayerPropertiesConstIterator::child_index () const
{
std::pair <size_t, size_t> f = factor ();
return ((m_uint / f.first) % f.second) - 1;
}
// -------------------------------------------------------------
// LayerPropertiesList implementation
LayerPropertiesList::LayerPropertiesList ()
: tl::Object (), m_list_index (0)
{
// .. nothing yet ..
}
LayerPropertiesList::~LayerPropertiesList ()
{
// .. nothing yet ..
}
LayerPropertiesList::LayerPropertiesList (const LayerPropertiesList &d)
: tl::Object (), m_list_index (0)
{
operator= (d);
}
LayerPropertiesList &
LayerPropertiesList::operator= (const LayerPropertiesList &d)
{
if (&d != this) {
m_layer_properties = d.m_layer_properties;
m_dither_pattern = d.m_dither_pattern;
m_line_styles = d.m_line_styles;
m_name = d.m_name;
}
return *this;
}
bool
LayerPropertiesList::operator== (const LayerPropertiesList &d) const
{
if (m_dither_pattern != d.m_dither_pattern) {
return false;
}
if (m_line_styles != d.m_line_styles) {
return false;
}
return m_layer_properties == d.m_layer_properties;
}
void
LayerPropertiesList::translate_cv_references (int cv_index)
{
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
if (l->source (false).cv_index () >= 0) {
ParsedLayerSource new_source (l->source (false));
new_source.cv_index (cv_index);
l->set_source (new_source);
}
}
}
static bool has_cv_ref (const LayerPropertiesNode &node, int cv_ref)
{
if (! node.has_children ()) {
return node.source (true).cv_index () == cv_ref && (node.is_cell_box_layer () || node.is_standard_layer ());
} else {
for (LayerPropertiesNode::const_iterator c = node.begin_children (); c != node.end_children (); ++c) {
if (! has_cv_ref (*c, cv_ref)) {
return false;
}
}
return true;
}
}
void
LayerPropertiesList::remove_cv_references (int cv_index, bool except)
{
std::vector<LayerPropertiesIterator> cv_ref;
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
if (has_cv_ref (*l, cv_index) != except) {
cv_ref.push_back (l);
}
}
std::sort (cv_ref.begin (), cv_ref.end (), CompareLayerIteratorBottomUp ());
for (std::vector<LayerPropertiesIterator>::const_iterator ll = cv_ref.begin (); ll != cv_ref.end (); ++ll) {
erase (*ll);
}
}
static bool has_wildcard_layout (const LayerPropertiesNode &node, bool any)
{
if (! node.has_children ()) {
return node.source (true).cv_index () < 0 && (node.is_cell_box_layer () || node.is_standard_layer ());
} else if (any) {
for (LayerPropertiesNode::const_iterator c = node.begin_children (); c != node.end_children (); ++c) {
if (has_wildcard_layout (*c, true)) {
return true;
}
}
return false;
} else {
for (LayerPropertiesNode::const_iterator c = node.begin_children (); c != node.end_children (); ++c) {
if (! has_wildcard_layout (*c, false)) {
return false;
}
}
return true;
}
}
static LayerPropertiesNode expand_wildcard_layout (const LayerPropertiesNode &source, int new_cv_index)
{
// this creates the node, not the children:
LayerPropertiesNode new_node ((const LayerProperties &) source);
if (! source.has_children ()) {
// a wildcard layout: need to replace the cv index:
ParsedLayerSource new_source (new_node.source (false));
new_source.cv_index (new_cv_index);
new_node.set_source (new_source);
} else {
for (LayerPropertiesNode::const_iterator l = source.begin_children (); l != source.end_children (); ++l) {
if (has_wildcard_layout (*l, true /*any*/)) {
// need to add a new child node
new_node.add_child (expand_wildcard_layout (*l, new_cv_index));
}
}
}
return new_node;
}
static std::vector<LayerPropertiesNode>
expand_wildcard_layers (const LayerPropertiesNode &lp, const LayerPropertiesList &current_props, lay::LayoutView *view, unsigned int list_index)
{
std::vector<LayerPropertiesNode> new_props;
int cv_index = lp.source (true).cv_index ();
if (cv_index >= 0 && cv_index < int (view->cellviews ())) {
// determine the layers not assigned so far.
// NOTE: we use lay::ParsedLayerSource, but in a normalized form that does not
// include transformations and such. Hence we really figure out which layer is
// missing or not.
std::set <lay::ParsedLayerSource> present;
for (LayerPropertiesConstIterator l = current_props.begin_const_recursive (); ! l.at_end (); ++l) {
if (! l->has_children ()) {
lay::ParsedLayerSource src = l->source (true /*real*/);
if (src.cv_index () == cv_index) {
present.insert (lay::ParsedLayerSource (src.layer_props (), cv_index));
}
}
}
std::vector <lay::ParsedLayerSource> actual;
const db::Layout &layout = view->cellview (cv_index)->layout ();
for (unsigned int l = 0; l < layout.layers (); ++l) {
if (layout.is_valid_layer (l)) {
actual.push_back (lay::ParsedLayerSource (layout.get_properties (l), cv_index));
}
}
std::sort (actual.begin (), actual.end ());
for (std::vector <lay::ParsedLayerSource>::const_iterator a = actual.begin (); a != actual.end (); ++a) {
if (present.find (*a) == present.end ()) {
// NOTE: initialization through LayerProperties creates a new ID
lay::LayerPropertiesNode node ((const LayerProperties &) lp);
node.attach_view (view, list_index);
// Build a new ParsedLayerSource combining the transformation, hierarchy levels and
// property selections from the wildcard one and the requested layer source
lay::ParsedLayerSource src (*a);
src += lp.source (true /*real*/);
node.set_source (src);
new_props.push_back (node);
}
}
}
return new_props;
}
void
LayerPropertiesList::append (const LayerPropertiesList &other)
{
lay::DitherPattern dp (other.dither_pattern ());
std::map <unsigned int, unsigned int> index_map;
dp.merge (dither_pattern (), index_map);
for (lay::LayerPropertiesIterator l = begin_recursive (); l != end_recursive (); ++l) {
int dpi = l->dither_pattern (false /*local*/);
std::map <unsigned int, unsigned int>::iterator m = index_map.find ((unsigned int) dpi);
if (m != index_map.end ()) {
l->set_dither_pattern (int (m->second));
}
}
set_dither_pattern (dp);
for (lay::LayerPropertiesList::const_iterator l = other.begin_const (); l != other.end_const (); ++l) {
push_back (*l);
}
}
void
LayerPropertiesList::expand (const std::map<int, int> &map_cv_index, bool add_default)
{
tl_assert (view () != 0);
// Add a default element if required unless there already is one at top level.
// If there already is one, this one will be ignored.
if (add_default) {
push_back (LayerPropertiesNode ());
}
// Apply cv mapping
if (! map_cv_index.empty ()) {
std::set<int> cvrefs_to_erase;
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
ParsedLayerSource new_source (l->source (false));
std::map<int, int>::const_iterator m = map_cv_index.end ();
if (new_source.cv_index () >= 0) {
m = map_cv_index.find (new_source.cv_index ());
}
if (m == map_cv_index.end () && !l->has_children ()) {
m = map_cv_index.find (-1);
}
if (m != map_cv_index.end ()) {
if (m->second == -2) {
// mapping to -2 means: remove
cvrefs_to_erase.insert (new_source.cv_index ());
} else {
new_source.cv_index (m->second);
l->set_source (new_source);
}
}
}
// erase the items specfied to removal (cv mapping to -1)
for (std::set<int>::const_iterator cv = cvrefs_to_erase.begin (); cv != cvrefs_to_erase.end (); ++cv) {
remove_cv_references (*cv, false);
}
}
// Test if any layer has a wildcard layout spec
bool lywc = false;
for (const_iterator l = begin (); l != end () && !lywc; ++l) {
lywc = has_wildcard_layout (*l, true /*any*/);
}
if (lywc) {
// If that is the case, iterate over all layouts (outer iteration) and create the
// wildcarded
std::vector <lay::LayerPropertiesNode> new_nodes;
for (unsigned int cv_index = 0; cv_index < view ()->cellviews (); ++cv_index) {
for (const_iterator l = begin (); l != end (); ++l) {
if (has_wildcard_layout (*l, true /*any*/)) {
new_nodes.push_back (expand_wildcard_layout (*l, cv_index));
}
}
}
for (std::vector <lay::LayerPropertiesNode>::const_iterator n = new_nodes.begin (); n != new_nodes.end (); ++n) {
push_back (*n);
back ().attach_view (view (), list_index ());
}
// Remove all layers which have been expanded and their parents
// if necessary
std::vector<LayerPropertiesIterator> expanded;
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
if (has_wildcard_layout (*l, false /*all*/)) {
expanded.push_back (l);
}
}
std::sort (expanded.begin (), expanded.end (), CompareLayerIteratorBottomUp ());
for (std::vector<LayerPropertiesIterator>::const_iterator ll = expanded.begin (); ll != expanded.end (); ++ll) {
erase (*ll);
}
}
// Expand layer wildcard layers
std::vector<LayerPropertiesIterator> lwc;
// find the wildcard layers
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
if (! l->has_children () && l->source (true).is_wildcard_layer ()) {
lwc.push_back (l);
}
}
// after this sort we can modify the entries without invalidating the following iterators
std::sort (lwc.begin (), lwc.end (), CompareLayerIteratorBottomUp ());
for (std::vector<LayerPropertiesIterator>::const_iterator ll = lwc.begin (); ll != lwc.end (); ++ll) {
LayerPropertiesIterator pos = *ll;
// Note: expand_wildcard_layers will recompute the already present layers on every call. Thus, only the
// first matching wildcard is effective.
std::vector <LayerPropertiesNode> new_nodes = expand_wildcard_layers (*pos, *this, view (), list_index ());
for (std::vector <LayerPropertiesNode>::const_iterator n = new_nodes.begin (); n != new_nodes.end (); ++n) {
insert (pos, *n);
pos.next_sibling ();
}
erase (pos);
}
// Assign default colors and stipples for layers without any ...
int stipple_index = 0;
for (LayerPropertiesIterator l = begin_recursive (); !l.at_end (); ++l) {
if (! l->has_children ()) {
if (l->frame_color (true) == 0) {
l->set_frame_color (view ()->get_palette ().luminous_color_by_index (l->source (true /*real*/).color_index ()));
}
if (l->fill_color (true) == 0) {
l->set_fill_color (view ()->get_palette ().luminous_color_by_index (l->source (true /*real*/).color_index ()));
}
if (l->dither_pattern (true) < 0) {
l->set_dither_pattern (view ()->get_stipple_palette ().standard_stipple_by_index (stipple_index));
}
++stipple_index;
}
}
}
LayerPropertiesConstIterator
LayerPropertiesList::begin_const_recursive () const
{
return LayerPropertiesConstIterator (*this);
}
LayerPropertiesConstIterator
LayerPropertiesList::end_const_recursive () const
{
return LayerPropertiesConstIterator (*this, true);
}
LayerPropertiesIterator
LayerPropertiesList::begin_recursive ()
{
return LayerPropertiesIterator (*this);
}
LayerPropertiesIterator
LayerPropertiesList::end_recursive ()
{
return LayerPropertiesIterator (*this, true);
}
LayerPropertiesList::const_iterator
LayerPropertiesList::begin_const () const
{
return m_layer_properties.begin ();
}
LayerPropertiesList::const_iterator
LayerPropertiesList::end_const () const
{
return m_layer_properties.end ();
}
LayerPropertiesList::iterator
LayerPropertiesList::begin ()
{
return m_layer_properties.begin ();
}
LayerPropertiesList::iterator
LayerPropertiesList::end ()
{
return m_layer_properties.end ();
}
LayerPropertiesNode &
LayerPropertiesList::back ()
{
return m_layer_properties.back ();
}
const LayerPropertiesNode &
LayerPropertiesList::back () const
{
return m_layer_properties.back ();
}
/**
* @brief A helper class for XML parser: convert a string to a color and vice versa
*/
struct UIntColorConverter
: private ColorConverter
{
std::string to_string (const color_t &c) const
{
if (c == 0) {
return "";
} else {
return ColorConverter::to_string (QColor (c & 0xffffff));
}
}
void from_string (const std::string &s, color_t &c) const
{
if (s.empty ()) {
c = 0;
} else {
QColor qc;
ColorConverter::from_string (s, qc);
c = qc.rgb () | 0xff000000;
}
}
};
/**
* @brief A helper class for XML parser: convert a string to a integer index and vice versa (with -1 being a blank string)
*/
struct WidthConverter
{
std::string to_string (int b) const
{
if (b < 0) {
return "";
} else {
return tl::to_string (b);
}
}
void from_string (const std::string &s, int &b) const
{
if (s.empty ()) {
b = -1;
} else {
tl::from_string (s.c_str (), b);
}
}
};
/**
* @brief A helper class for XML parser: convert a string to a integer index and vice versa
*/
struct DitherPatternIndexConverter
{
std::string to_string (int b) const
{
if (b < 0) {
return "";
} else if (b < std::distance (lay::DitherPattern::default_pattern ().begin (), lay::DitherPattern::default_pattern ().begin_custom ())) {
// intrinsic pattern
return "I" + tl::to_string (b);
} else {
// custom pattern
return "C" + tl::to_string (b - std::distance (lay::DitherPattern::default_pattern ().begin (), lay::DitherPattern::default_pattern ().begin_custom ()));
}
}
void from_string (const std::string &s, int &b) const
{
if (s.empty ()) {
b = -1;
} else if (s[0] == 'I') {
tl::from_string (s.c_str () + 1, b);
} else if (s[0] == 'C') {
tl::from_string (s.c_str () + 1, b);
b = b + std::distance (lay::DitherPattern::default_pattern ().begin (), lay::DitherPattern::default_pattern ().begin_custom ());
} else {
tl::from_string (s, b);
if (b >= 16) {
// backward compatibility to older versions
b = b - 16 + std::distance (lay::DitherPattern::default_pattern ().begin (), lay::DitherPattern::default_pattern ().begin_custom ());
}
}
}
};
/**
* @brief A helper class for XML parser: convert a style string to a integer index and vice versa
*/
struct LineStyleIndexConverter
{
std::string to_string (int b) const
{
if (b < 0) {
return "";
} else if (b < std::distance (lay::LineStyles::default_style ().begin (), lay::LineStyles::default_style ().begin_custom ())) {
// intrinsic pattern
return "I" + tl::to_string (b);
} else {
// custom pattern
return "C" + tl::to_string (b - std::distance (lay::LineStyles::default_style ().begin (), lay::LineStyles::default_style ().begin_custom ()));
}
}
void from_string (const std::string &s, int &b) const
{
if (s.empty ()) {
b = -1;
} else if (s[0] == 'I') {
tl::from_string (s.c_str () + 1, b);
} else if (s[0] == 'C') {
tl::from_string (s.c_str () + 1, b);
b = b + std::distance (lay::LineStyles::default_style ().begin (), lay::LineStyles::default_style ().begin_custom ());
} else {
tl::from_string (s, b);
if (b >= 16) {
// backward compatibility to older versions
b = b - 16 + std::distance (lay::LineStyles::default_style ().begin (), lay::LineStyles::default_style ().begin_custom ());
}
}
}
};
static const tl::XMLElementList layer_element = tl::XMLElementList (
// HINT: these make_member calls want to be qualified: otherwise an internal error
// was observed ..
tl::make_member<lay::color_t, LayerPropertiesNode> (&LayerPropertiesNode::frame_color_loc, &LayerPropertiesNode::set_frame_color_code, "frame-color", UIntColorConverter ()) +
tl::make_member<lay::color_t, LayerPropertiesNode> (&LayerPropertiesNode::fill_color_loc, &LayerPropertiesNode::set_fill_color_code, "fill-color", UIntColorConverter ()) +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::frame_brightness_loc, &LayerPropertiesNode::set_frame_brightness, "frame-brightness") +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::fill_brightness_loc, &LayerPropertiesNode::set_fill_brightness, "fill-brightness") +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::dither_pattern_loc, &LayerPropertiesNode::set_dither_pattern, "dither-pattern", DitherPatternIndexConverter ()) +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::line_style_loc, &LayerPropertiesNode::set_line_style, "line-style", LineStyleIndexConverter ()) +
tl::make_member<bool, LayerPropertiesNode> (&LayerPropertiesNode::valid_loc, &LayerPropertiesNode::set_valid, "valid") +
tl::make_member<bool, LayerPropertiesNode> (&LayerPropertiesNode::visible_loc, &LayerPropertiesNode::set_visible, "visible") +
tl::make_member<bool, LayerPropertiesNode> (&LayerPropertiesNode::transparent_loc, &LayerPropertiesNode::set_transparent, "transparent") +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::width_loc, &LayerPropertiesNode::set_width, "width", WidthConverter ()) +
tl::make_member<bool, LayerPropertiesNode> (&LayerPropertiesNode::marked_loc, &LayerPropertiesNode::set_marked, "marked") +
tl::make_member<bool, LayerPropertiesNode> (&LayerPropertiesNode::xfill_loc, &LayerPropertiesNode::set_xfill, "xfill") +
tl::make_member<int, LayerPropertiesNode> (&LayerPropertiesNode::animation_loc, &LayerPropertiesNode::set_animation, "animation") +
tl::make_member<std::string, LayerPropertiesNode> (&LayerPropertiesNode::name, &LayerPropertiesNode::set_name, "name") +
tl::make_member<std::string, LayerPropertiesNode> (&LayerPropertiesNode::source_string_loc, &LayerPropertiesNode::set_source, "source") +
tl::make_element<LayerPropertiesNode, LayerPropertiesNode::const_iterator, LayerPropertiesNode> (&LayerPropertiesNode::begin_children, &LayerPropertiesNode::end_children, &LayerPropertiesNode::add_child, "group-members", &layer_element)
);
static const tl::XMLElementList layer_prop_list = tl::XMLElementList (
tl::make_element<LayerPropertiesNode, LayerPropertiesList::const_iterator, LayerPropertiesList> (&LayerPropertiesList::begin_const, &LayerPropertiesList::end_const, &LayerPropertiesList::push_back, "properties", &layer_element) +
tl::make_member (&LayerPropertiesList::name, &LayerPropertiesList::set_name, "name") +
tl::make_element (&LayerPropertiesList::begin_custom_dither_pattern, &LayerPropertiesList::end_custom_dither_pattern, &LayerPropertiesList::push_custom_dither_pattern, "custom-dither-pattern",
tl::make_element (&lay::DitherPatternInfo::to_strings, &lay::DitherPatternInfo::from_strings, "pattern",
tl::make_member<std::string, std::vector<std::string>::const_iterator, std::vector<std::string> > (&std::vector<std::string>::begin, &std::vector<std::string>::end, &std::vector<std::string>::push_back, "line")
) +
tl::make_member (&lay::DitherPatternInfo::order_index, &lay::DitherPatternInfo::set_order_index, "order") +
tl::make_member (&lay::DitherPatternInfo::name, &lay::DitherPatternInfo::set_name, "name")
) +
tl::make_element (&LayerPropertiesList::begin_custom_line_styles, &LayerPropertiesList::end_custom_line_styles, &LayerPropertiesList::push_custom_line_style, "custom-line-style",
tl::make_member (&lay::LineStyleInfo::to_string, &lay::LineStyleInfo::from_string, "pattern") +
tl::make_member (&lay::LineStyleInfo::order_index, &lay::LineStyleInfo::set_order_index, "order") +
tl::make_member (&lay::LineStyleInfo::name, &lay::LineStyleInfo::set_name, "name")
)
);
// declaration of the layer properties file XML structure
static const tl::XMLStruct <LayerPropertiesList>
layer_prop_list_structure ("layer-properties", &layer_prop_list);
// declaration of the layer properties file XML structure for a multi-tab file
static const tl::XMLStruct <std::vector<LayerPropertiesList> >
layer_prop_lists_structure ("layer-properties-tabs",
tl::make_element<LayerPropertiesList, std::vector<LayerPropertiesList>::const_iterator, std::vector<LayerPropertiesList> > (&std::vector<LayerPropertiesList>::begin, &std::vector<LayerPropertiesList>::end, &std::vector<LayerPropertiesList>::push_back, "layer-properties", &layer_prop_list)
);
const tl::XMLElementList *
LayerPropertiesList::xml_format ()
{
return &layer_prop_list;
}
void
LayerPropertiesList::load (tl::XMLSource &stream)
{
layer_prop_list_structure.parse (stream, *this);
}
void
LayerPropertiesList::save (tl::OutputStream &os) const
{
layer_prop_list_structure.write (os, *this);
}
void
LayerPropertiesList::load (tl::XMLSource &stream, std::vector <lay::LayerPropertiesList> &properties_lists)
{
try {
// "old" way
lay::LayerPropertiesList properties_list;
layer_prop_list_structure.parse (stream, properties_list);
properties_lists.push_back (properties_list);
} catch (...) {
// "new" way
stream.source ()->reset ();
layer_prop_lists_structure.parse (stream, properties_lists);
}
}
void
LayerPropertiesList::save (tl::OutputStream &os, const std::vector <lay::LayerPropertiesList> &properties_lists)
{
layer_prop_lists_structure.write (os, properties_lists);
}
void
LayerPropertiesList::attach_view (lay::LayoutView *view, unsigned int list_index)
{
mp_view.reset (view);
m_list_index = list_index;
// HINT: this method has the side effect of recomputing the layer source parameters.
// The action must not be suppressed if view == mp_view
for (layer_list::iterator c = m_layer_properties.begin (); c != m_layer_properties.end (); ++c) {
c->attach_view (view, list_index);
}
}
lay::LayoutView *
LayerPropertiesList::view () const
{
return const_cast<lay::LayoutView *> (mp_view.get ());
}
unsigned int
LayerPropertiesList::list_index () const
{
return m_list_index;
}
void
LayerPropertiesList::push_back (const LayerPropertiesNode &d)
{
m_layer_properties.push_back (d);
}
void
LayerPropertiesList::set_dither_pattern (const lay::DitherPattern &pattern)
{
m_dither_pattern = pattern;
}
void
LayerPropertiesList::set_line_styles (const lay::LineStyles &styles)
{
m_line_styles = styles;
}
LayerPropertiesNode &
LayerPropertiesList::insert (const LayerPropertiesIterator &iter, const LayerPropertiesNode &node)
{
tl_assert (! iter.is_null ());
LayerPropertiesNode *ret = 0;
LayerPropertiesIterator parent = iter.parent ();
if (parent.is_null ()) {
ret = &*(m_layer_properties.insert (m_layer_properties.begin () + iter.child_index (), node));
} else {
ret = &(parent->insert_child (parent->begin_children () + iter.child_index (), node));
}
// attach the new object to the view
ret->attach_view (view (), list_index ());
return *ret;
}
void
LayerPropertiesList::erase (const LayerPropertiesIterator &iter)
{
tl_assert (! iter.is_null ());
std::pair <LayerPropertiesNode *, size_t> pp = iter.parent_obj ();
if (pp.first == 0) {
m_layer_properties.erase (m_layer_properties.begin () + pp.second);
} else {
pp.first->erase_child (pp.first->begin_children () + pp.second);
}
}
// -------------------------------------------------------------
// LayerPropertiesNodeRef implementation
LayerPropertiesNodeRef::LayerPropertiesNodeRef (LayerPropertiesNode *node)
: m_iter (node)
{
if (node) {
// NOTE: we do assignment before we set the iterator reference - hence there won't be
// updates triggered.
LayerPropertiesNode::operator= (*node);
// Makes ourself a perfect copy of the original (including reference into the view)
attach_view (node->view (), node->list_index ());
set_parent (node->parent ());
mp_iter.reset (&m_iter);
mp_node.reset (node);
}
}
LayerPropertiesNodeRef::LayerPropertiesNodeRef (LayerPropertiesConstIterator *iter)
{
if (iter && !iter->at_end () && !iter->is_null ()) {
const lay::LayerPropertiesNode *node = (*iter).operator-> ();
// NOTE: we do assignment before we set the iterator reference - hence there won't be
// updates triggered.
LayerPropertiesNode::operator= (*node);
// Makes ourself a perfect copy of the original (including reference into the view)
attach_view (node->view (), node->list_index ());
set_parent (node->parent ());
mp_iter.reset (iter);
mp_node.reset (const_cast<lay::LayerPropertiesNode *> (node));
}
}
LayerPropertiesNodeRef::LayerPropertiesNodeRef (const LayerPropertiesConstIterator &iter)
: m_iter (iter)
{
if (!iter.at_end () && !iter.is_null ()) {
const lay::LayerPropertiesNode *node = iter.operator-> ();
// NOTE: we do assignment before we set the iterator reference - hence there won't be
// updates triggered.
LayerPropertiesNode::operator= (*node);
// Makes ourself a perfect copy of the original (including reference into the view)
attach_view (node->view (), node->list_index ());
set_parent (node->parent ());
mp_iter.reset (&m_iter);
mp_node.reset (const_cast<lay::LayerPropertiesNode *> (node));
}
}
LayerPropertiesNodeRef::LayerPropertiesNodeRef ()
{
// .. nothing yet ..
}
LayerPropertiesNodeRef::LayerPropertiesNodeRef (const LayerPropertiesNodeRef &other)
: LayerPropertiesNode (other), m_iter (other.m_iter), mp_iter (other.mp_iter), mp_node (other.mp_node)
{
attach_view (other.view (), other.list_index ());
set_parent (other.parent ());
}
LayerPropertiesNodeRef &LayerPropertiesNodeRef::operator= (const LayerPropertiesNodeRef &other)
{
if (this != &other) {
mp_iter = other.mp_iter;
mp_node = other.mp_node;
m_iter = other.m_iter;
attach_view (other.view (), other.list_index ());
set_parent (other.parent ());
// NOTE: this will update the view
LayerPropertiesNode::operator= (other);
}
return *this;
}
void
LayerPropertiesNodeRef::erase ()
{
if (is_valid ()) {
view ()->delete_layer ((unsigned int) list_index (), *mp_iter);
}
}
const lay::LayerPropertiesConstIterator &
LayerPropertiesNodeRef::iter () const
{
if (mp_iter) {
return *mp_iter;
} else {
static lay::LayerPropertiesConstIterator null_iter;
return null_iter;
}
}
bool
LayerPropertiesNodeRef::is_valid () const
{
return mp_iter && !mp_iter->at_end () && !mp_iter->is_null () && view ();
}
void
LayerPropertiesNodeRef::need_realize (unsigned int flags, bool force)
{
LayerPropertiesNode::need_realize (flags, force);
if (is_valid ()) {
if ((flags & (nr_visual + nr_source)) != 0) {
view ()->set_properties ((unsigned int) list_index (), *mp_iter, *this);
}
if ((flags & nr_hierarchy) != 0) {
view ()->replace_layer_node ((unsigned int) list_index (), *mp_iter, *this);
}
} else if (mp_node) {
// fallback mode is to use the target node directly.
*mp_node = *this;
}
}
} // namespace lay