mirror of https://github.com/KLayout/klayout.git
New methods: Layout#copy_layer, Layout#move_layer and Layout#clear_layer with shape selector, Shapes#clear with shape selector
This commit is contained in:
parent
987bb005da
commit
f11500996f
|
|
@ -187,6 +187,17 @@ Cell::clear (unsigned int index)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::clear (unsigned int index, unsigned int types)
|
||||
{
|
||||
shapes_map::iterator s = m_shapes_map.find(index);
|
||||
if (s != m_shapes_map.end() && ! s->second.empty ()) {
|
||||
mp_layout->invalidate_bboxes (index); // HINT: must come before the change is done!
|
||||
s->second.clear (types);
|
||||
m_bbox_needs_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
Cell::shapes_type &
|
||||
Cell::shapes (unsigned int index)
|
||||
{
|
||||
|
|
@ -344,6 +355,20 @@ Cell::copy (unsigned int src, unsigned int dest)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::copy (unsigned int src, unsigned int dest, unsigned int types)
|
||||
{
|
||||
if (src != dest) {
|
||||
shapes (dest).insert (shapes (src), types);
|
||||
} else {
|
||||
// When duplicating the layer, first create a copy to avoid problems with non-stable containers
|
||||
// Hint: using the assignment and not the copy ctor does not copy the db::Manager association.
|
||||
db::Shapes shape_copy;
|
||||
shape_copy.insert (shapes (src), types);
|
||||
shapes (dest).insert (shape_copy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::move (unsigned int src, unsigned int dest)
|
||||
{
|
||||
|
|
@ -353,6 +378,15 @@ Cell::move (unsigned int src, unsigned int dest)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::move (unsigned int src, unsigned int dest, unsigned int types)
|
||||
{
|
||||
if (src != dest) {
|
||||
copy (src, dest, types);
|
||||
clear (src, types);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::swap (unsigned int i1, unsigned int i2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -182,6 +182,13 @@ public:
|
|||
*/
|
||||
void copy (unsigned int src, unsigned int dest);
|
||||
|
||||
/**
|
||||
* @brief Copy the shapes from layer src to dest (only shapes from given classes)
|
||||
*
|
||||
* The target layer is not overwritten. Instead, the shapes are added to the target layer's shapes.
|
||||
*/
|
||||
void copy (unsigned int src, unsigned int dest, unsigned int types);
|
||||
|
||||
/**
|
||||
* @brief Move the shapes from layer src to dest
|
||||
*
|
||||
|
|
@ -189,6 +196,13 @@ public:
|
|||
*/
|
||||
void move (unsigned int src, unsigned int dest);
|
||||
|
||||
/**
|
||||
* @brief Move the shapes from layer src to dest (only shapes from given classes)
|
||||
*
|
||||
* The target layer is not overwritten. Instead, the shapes are added to the target layer's shapes.
|
||||
*/
|
||||
void move (unsigned int src, unsigned int dest, unsigned int types);
|
||||
|
||||
/**
|
||||
* @brief Swap the layers given
|
||||
*/
|
||||
|
|
@ -199,7 +213,12 @@ public:
|
|||
*/
|
||||
void clear (unsigned int index);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Clear the shapes on the given layer (only the shapes from the given classes)
|
||||
*/
|
||||
void clear (unsigned int index, unsigned int types);
|
||||
|
||||
/**
|
||||
* @brief Erase a cell instance given by a instance proxy
|
||||
*
|
||||
* Erasing a cell instance will destroy the sorting order and invalidate
|
||||
|
|
|
|||
|
|
@ -1971,7 +1971,19 @@ Layout::move_layer (unsigned int src, unsigned int dest)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Layout::move_layer (unsigned int src, unsigned int dest, unsigned int flags)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (src) != LayoutLayers::Free);
|
||||
tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free);
|
||||
|
||||
// move the shapes
|
||||
for (iterator c = begin (); c != end (); ++c) {
|
||||
c->move (src, dest, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::copy_layer (unsigned int src, unsigned int dest)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (src) != LayoutLayers::Free);
|
||||
|
|
@ -1983,7 +1995,19 @@ Layout::copy_layer (unsigned int src, unsigned int dest)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Layout::copy_layer (unsigned int src, unsigned int dest, unsigned int flags)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (src) != LayoutLayers::Free);
|
||||
tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free);
|
||||
|
||||
// copy the shapes
|
||||
for (iterator c = begin (); c != end (); ++c) {
|
||||
c->copy (src, dest, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::clear_layer (unsigned int n)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (n) != LayoutLayers::Free);
|
||||
|
|
@ -1994,7 +2018,18 @@ Layout::clear_layer (unsigned int n)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Layout::clear_layer (unsigned int n, unsigned int flags)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (n) != LayoutLayers::Free);
|
||||
|
||||
// clear the shapes
|
||||
for (iterator c = begin (); c != end (); ++c) {
|
||||
c->clear (n, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::delete_layer (unsigned int n)
|
||||
{
|
||||
tl_assert (m_layers.layer_state (n) != LayoutLayers::Free);
|
||||
|
|
|
|||
|
|
@ -1377,7 +1377,15 @@ public:
|
|||
*/
|
||||
void move_layer (unsigned int src, unsigned int dest);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Move a layer (selected shape types only)
|
||||
*
|
||||
* Move a layer from the source to the target. The target is not cleared before, so that this method
|
||||
* merges shapes from the source with the target layer. The source layer is empty after that operation.
|
||||
*/
|
||||
void move_layer (unsigned int src, unsigned int dest, unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief Copy a layer
|
||||
*
|
||||
* Copy a layer from the source to the target. The target is not cleared before, so that this method
|
||||
|
|
@ -1385,14 +1393,29 @@ public:
|
|||
*/
|
||||
void copy_layer (unsigned int src, unsigned int dest);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Copy a layer (selected shape types only)
|
||||
*
|
||||
* Copy a layer from the source to the target. The target is not cleared before, so that this method
|
||||
* merges shapes from the source with the target layer.
|
||||
*/
|
||||
void copy_layer (unsigned int src, unsigned int dest, unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief Clear a layer
|
||||
*
|
||||
* Clears the layer: removes all shapes.
|
||||
*/
|
||||
void clear_layer (unsigned int n);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Clear a layer (selected shapes only)
|
||||
*
|
||||
* Clears the layer: removes the shapes of the type given the flags (ShapeIterator::shapes_type)
|
||||
*/
|
||||
void clear_layer (unsigned int n, unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief Delete a layer
|
||||
*
|
||||
* This does free the shapes of the cells and remembers the
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ inline bool needs_translate (object_tag<Sh> /*tag*/)
|
|||
return tl::is_equal_type<typename shape_traits<Sh>::can_deref, tl::True> () || tl::is_equal_type<typename shape_traits<Sh>::is_array, tl::True> ();
|
||||
}
|
||||
|
||||
inline bool type_mask_applies (const db::LayerBase *layer, unsigned int flags)
|
||||
{
|
||||
unsigned int tm = layer->type_mask ();
|
||||
return (((flags & db::ShapeIterator::Properties) == 0 || (tm & db::ShapeIterator::Properties) != 0) && (flags & tm) != 0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// layer_op implementation
|
||||
|
||||
|
|
@ -214,7 +220,13 @@ Shapes::insert (const Shapes &d)
|
|||
}
|
||||
|
||||
void
|
||||
Shapes::do_insert (const Shapes &d)
|
||||
Shapes::insert (const Shapes &d, unsigned int flags)
|
||||
{
|
||||
do_insert (d, flags);
|
||||
}
|
||||
|
||||
void
|
||||
Shapes::do_insert (const Shapes &d, unsigned int flags)
|
||||
{
|
||||
// shortcut for "nothing to do"
|
||||
if (d.empty ()) {
|
||||
|
|
@ -228,10 +240,12 @@ Shapes::do_insert (const Shapes &d)
|
|||
|
||||
m_layers.reserve (d.m_layers.size ());
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
m_layers.push_back ((*l)->clone ());
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
manager ()->queue (this, new FullLayerOp (true, m_layers.back ()));
|
||||
if (type_mask_applies (*l, flags)) {
|
||||
m_layers.push_back ((*l)->clone ());
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
manager ()->queue (this, new FullLayerOp (true, m_layers.back ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +253,9 @@ Shapes::do_insert (const Shapes &d)
|
|||
|
||||
} else {
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
(*l)->insert_into (this);
|
||||
if (type_mask_applies (*l, flags)) {
|
||||
(*l)->insert_into (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,14 +263,18 @@ Shapes::do_insert (const Shapes &d)
|
|||
|
||||
// the target is standalone - dereference
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
(*l)->deref_into (this);
|
||||
if (type_mask_applies (*l, flags)) {
|
||||
(*l)->deref_into (this);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// both shape containers are in separate spaces - translate
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
(*l)->translate_into (this, shape_repository (), array_repository ());
|
||||
if (type_mask_applies (*l, flags)) {
|
||||
(*l)->translate_into (this, shape_repository (), array_repository ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1046,6 +1066,41 @@ Shapes::clear ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Shapes::clear (unsigned int flags)
|
||||
{
|
||||
if (!m_layers.empty ()) {
|
||||
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
||||
tl::vector<LayerBase *> new_layers;
|
||||
|
||||
for (tl::vector<LayerBase *>::const_iterator l = m_layers.end (); l != m_layers.begin (); ) {
|
||||
|
||||
// because the undo stack will do a push, we need to remove layers from the back (this is the last undo
|
||||
// element to be executed)
|
||||
--l;
|
||||
|
||||
if (type_mask_applies (*l, flags)) {
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
manager ()->queue (this, new FullLayerOp (false, (*l)));
|
||||
} else {
|
||||
delete *l;
|
||||
}
|
||||
|
||||
} else {
|
||||
new_layers.push_back (*l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_layers.swap (new_layers);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Shapes::reset_bbox_dirty ()
|
||||
{
|
||||
set_dirty (false);
|
||||
|
|
|
|||
|
|
@ -628,6 +628,18 @@ public:
|
|||
*/
|
||||
void insert (const Shapes &d);
|
||||
|
||||
/**
|
||||
* @brief Insert all shapes from another container using the given shape types only
|
||||
*
|
||||
* This method insert all shapes from the given shape container.
|
||||
*
|
||||
* HINT: This method can duplicate shape containers from one layout to another.
|
||||
* The current implementation does not translate property Id's.
|
||||
* It is mainly intended for 1-to-1 copies of layouts where the whole
|
||||
* property repository is copied.
|
||||
*/
|
||||
void insert (const Shapes &d, unsigned int types);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator with transformation
|
||||
*
|
||||
|
|
@ -1219,6 +1231,11 @@ public:
|
|||
*/
|
||||
void clear ();
|
||||
|
||||
/**
|
||||
* @brief Clears the collection (given shape types only)
|
||||
*/
|
||||
void clear (unsigned int types);
|
||||
|
||||
/**
|
||||
* @brief Report the type mask of the objects stored herein
|
||||
*
|
||||
|
|
@ -1515,7 +1532,7 @@ private:
|
|||
db::Cell *mp_cell; // HINT: contains "dirty" in bit 0 and "editable" in bit 1
|
||||
|
||||
void invalidate_state ();
|
||||
void do_insert (const Shapes &d);
|
||||
void do_insert (const Shapes &d, unsigned int flags = db::ShapeIterator::All);
|
||||
void check_is_editable_for_undo_redo () const;
|
||||
|
||||
// gets the layers array
|
||||
|
|
|
|||
|
|
@ -1682,29 +1682,53 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"@param a The first of the layers to swap.\n"
|
||||
"@param b The second of the layers to swap.\n"
|
||||
) +
|
||||
gsi::method ("move_layer", &db::Layout::move_layer, gsi::arg ("src"), gsi::arg ("dest"),
|
||||
gsi::method ("move_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int)> (&db::Layout::move_layer), gsi::arg ("src"), gsi::arg ("dest"),
|
||||
"@brief Moves a layer\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.19.\n"
|
||||
"\n"
|
||||
"Move a layer from the source to the target. The target is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the target layer. The source layer is empty after that operation.\n"
|
||||
"Moves a layer from the source to the destination layer. The target is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the destination layer. The source layer is empty after that operation.\n"
|
||||
"\n"
|
||||
"@param src The layer index of the source layer.\n"
|
||||
"@param dest The layer index of the destination layer.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.19.\n"
|
||||
) +
|
||||
gsi::method ("copy_layer", &db::Layout::copy_layer, gsi::arg ("src"), gsi::arg ("dest"),
|
||||
gsi::method ("move_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int, unsigned int)> (&db::Layout::move_layer), gsi::arg ("src"), gsi::arg ("dest"), gsi::arg ("flags"),
|
||||
"@brief Moves a layer (selected shape types only)\n"
|
||||
"\n"
|
||||
"Moves a layer from the source to the destination layer. The target is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the destination layer. The copied shapes are removed from the source layer.\n"
|
||||
"\n"
|
||||
"@param src The layer index of the source layer.\n"
|
||||
"@param dest The layer index of the destination layer.\n"
|
||||
"@param flags A combination of the shape type flags from \\Shapes, S... constants\n"
|
||||
"\n"
|
||||
"This method variant has been introduced in version 0.28.9.\n"
|
||||
) +
|
||||
gsi::method ("copy_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int)> (&db::Layout::copy_layer), gsi::arg ("src"), gsi::arg ("dest"),
|
||||
"@brief Copies a layer\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.19.\n"
|
||||
"\n"
|
||||
"Copy a layer from the source to the target. The target is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the target layer.\n"
|
||||
"Copies a layer from the source to the destination layer. The destination layer is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the destination layer.\n"
|
||||
"\n"
|
||||
"@param src The layer index of the source layer.\n"
|
||||
"@param dest The layer index of the destination layer.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.19.\n"
|
||||
) +
|
||||
gsi::method ("clear_layer", &db::Layout::clear_layer, gsi::arg ("layer_index"),
|
||||
gsi::method ("copy_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int, unsigned int)> (&db::Layout::copy_layer), gsi::arg ("src"), gsi::arg ("dest"), gsi::arg ("flags"),
|
||||
"@brief Copies a layer (selected shape types only)\n"
|
||||
"\n"
|
||||
"Copies a layer from the source to the destination layer. The destination layer is not cleared before, so that this method \n"
|
||||
"merges shapes from the source with the destination layer.\n"
|
||||
"\n"
|
||||
"@param src The layer index of the source layer.\n"
|
||||
"@param dest The layer index of the destination layer.\n"
|
||||
"@param flags A combination of the shape type flags from \\Shapes, S... constants\n"
|
||||
"\n"
|
||||
"This method variant has been introduced in version 0.28.9.\n"
|
||||
) +
|
||||
gsi::method ("clear_layer", static_cast<void (db::Layout::*) (unsigned int)> (&db::Layout::clear_layer), gsi::arg ("layer_index"),
|
||||
"@brief Clears a layer\n"
|
||||
"\n"
|
||||
"Clears the layer: removes all shapes.\n"
|
||||
|
|
@ -1712,6 +1736,16 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This method was introduced in version 0.19.\n"
|
||||
"\n"
|
||||
"@param layer_index The index of the layer to delete.\n"
|
||||
) +
|
||||
gsi::method ("clear_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int)> (&db::Layout::clear_layer), gsi::arg ("layer_index"), gsi::arg ("flags"),
|
||||
"@brief Clears a layer (given shape types only)\n"
|
||||
"\n"
|
||||
"Clears the layer: removes all shapes for the given shape types.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.28.9.\n"
|
||||
"\n"
|
||||
"@param layer_index The index of the layer to delete.\n"
|
||||
"@param flags The type selector for the shapes to delete (see \\Shapes class, S... constants).\n"
|
||||
) +
|
||||
gsi::method ("delete_layer", &db::Layout::delete_layer, gsi::arg ("layer_index"),
|
||||
"@brief Deletes a layer\n"
|
||||
|
|
|
|||
|
|
@ -108,47 +108,47 @@ static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin (const db
|
|||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin (flags));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_all (const db::Shapes *s)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_all (const db::Shapes *s)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin (db::ShapeIterator::All));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_overlapping (const db::Shapes *s, unsigned int flags, const db::Box ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_overlapping (const db::Shapes *s, unsigned int flags, const db::Box ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_overlapping (region, flags));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_doverlapping (const db::Shapes *s, unsigned int flags, const db::DBox ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_doverlapping (const db::Shapes *s, unsigned int flags, const db::DBox ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_overlapping_all (const db::Shapes *s, const db::Box ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_overlapping_all (const db::Shapes *s, const db::Box ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_overlapping (region, db::ShapeIterator::All));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_doverlapping_all (const db::Shapes *s, const db::DBox ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_doverlapping_all (const db::Shapes *s, const db::DBox ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_touching (const db::Shapes *s, unsigned int flags, const db::Box ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_touching (const db::Shapes *s, unsigned int flags, const db::Box ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_touching (region, flags));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_dtouching (const db::Shapes *s, unsigned int flags, const db::DBox ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_dtouching (const db::Shapes *s, unsigned int flags, const db::DBox ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_touching_all (const db::Shapes *s, const db::Box ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_touching_all (const db::Shapes *s, const db::Box ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_touching (region, db::ShapeIterator::All));
|
||||
}
|
||||
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator>begin_dtouching_all (const db::Shapes *s, const db::DBox ®ion)
|
||||
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_dtouching_all (const db::Shapes *s, const db::DBox ®ion)
|
||||
{
|
||||
return gsi::layout_locking_iterator1<db::Shapes::shape_iterator> (s->layout (), s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All));
|
||||
}
|
||||
|
|
@ -251,12 +251,7 @@ static void insert_shapes (db::Shapes *sh, const db::Shapes &s)
|
|||
|
||||
static void insert_shapes_with_flags (db::Shapes *sh, const db::Shapes &s, unsigned int flags)
|
||||
{
|
||||
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
|
||||
// lock the layout against updates while inserting
|
||||
db::LayoutLocker locker (sh->layout ());
|
||||
for (db::Shapes::shape_iterator i = s.begin (flags); !i.at_end(); ++i) {
|
||||
sh->insert (*i);
|
||||
}
|
||||
sh->insert (s, flags);
|
||||
}
|
||||
|
||||
static void insert_shapes_with_trans (db::Shapes *sh, const db::Shapes &s, const db::ICplxTrans &trans)
|
||||
|
|
@ -1264,9 +1259,15 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
|
|||
"@brief Returns a value indicating whether the shapes container is empty\n"
|
||||
"This method has been introduced in version 0.20.\n"
|
||||
) +
|
||||
gsi::method ("clear", &db::Shapes::clear,
|
||||
gsi::method ("clear", static_cast<void (db::Shapes::*) ()> (&db::Shapes::clear),
|
||||
"@brief Clears the shape container\n"
|
||||
"This method has been introduced in version 0.16. It can only be used in editable mode."
|
||||
"This method has been introduced in version 0.16."
|
||||
) +
|
||||
gsi::method ("clear", static_cast<void (db::Shapes::*) (unsigned int)> (&db::Shapes::clear), gsi::arg ("flags"),
|
||||
"@brief Clears certain shape types from the shape container\n"
|
||||
"Only shapes matching the shape types from 'flags' are removed. 'flags' is a combination of the S... constants.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.9."
|
||||
) +
|
||||
gsi::method_ext ("size", &shapes_size,
|
||||
"@brief Gets the number of shapes in this container\n"
|
||||
|
|
@ -1296,10 +1297,19 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
|
|||
"returned for future references."
|
||||
) +
|
||||
gsi::method ("SAll|#s_all", &s_all,
|
||||
"@brief Indicates that all shapes shall be retrieved"
|
||||
"@brief Indicates that all shapes shall be retrieved\n"
|
||||
"You can use this constant to construct 'except' classes - e.g. "
|
||||
"to specify 'all shape types except boxes' use\n"
|
||||
"\n"
|
||||
"@code SAll - SBoxes @/code\n"
|
||||
) +
|
||||
gsi::method ("SAllWithProperties|#s_all_with_properties", &s_all_with_properties,
|
||||
"@brief Indicates that all shapes with properties shall be retrieved"
|
||||
"@brief Indicates that all shapes with properties shall be retrieved\n"
|
||||
"Using this selector means to retrieve only shapes with properties."
|
||||
"You can use this constant to construct 'except' classes - e.g. "
|
||||
"to specify 'all shape types with properties except boxes' use\n"
|
||||
"\n"
|
||||
"@code SAllWithProperties - SBoxes @/code\n"
|
||||
) +
|
||||
gsi::method ("SPolygons|#s_polygons", &s_polygons,
|
||||
"@brief Indicates that polygons shall be retrieved"
|
||||
|
|
@ -1333,7 +1343,10 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
|
|||
"@brief Indicates that user objects shall be retrieved"
|
||||
) +
|
||||
gsi::method ("SProperties|#s_properties", &s_properties,
|
||||
"@brief Indicates that only shapes with properties shall be retrieved"
|
||||
"@brief Indicates that only shapes with properties shall be retrieved\n"
|
||||
"You can or-combine this flag with the plain shape types to select a "
|
||||
"certain shape type, but only those shapes with properties. For example to "
|
||||
"select boxes with properties, use 'SProperties | SBoxes'."
|
||||
) +
|
||||
gsi::method_ext ("dump_mem_statistics", &dump_mem_statistics, gsi::arg<bool> ("detailed", false),
|
||||
"@hide"
|
||||
|
|
|
|||
|
|
@ -1925,6 +1925,51 @@ TEST(7)
|
|||
}
|
||||
}
|
||||
|
||||
// copy, move, clear with shape types
|
||||
TEST(8)
|
||||
{
|
||||
db::Manager m (true);
|
||||
|
||||
db::Layout layout (&m);
|
||||
unsigned int lindex1 = layout.insert_layer ();
|
||||
unsigned int lindex2 = layout.insert_layer ();
|
||||
|
||||
db::Cell &topcell = layout.cell (layout.add_cell ("TOP"));
|
||||
|
||||
topcell.shapes (lindex1).insert (db::Box (1, 2, 3, 4));
|
||||
topcell.shapes (lindex1).insert (db::Polygon (db::Box (1, 2, 3, 4)));
|
||||
|
||||
{
|
||||
db::Transaction trans (&m, "T1");
|
||||
topcell.shapes (lindex2).insert (topcell.shapes (lindex1));
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "polygon (1,2;1,4;3,4;3,2) #0\nbox (1,2;3,4) #0\n");
|
||||
}
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "");
|
||||
|
||||
{
|
||||
db::Transaction trans (&m, "T1");
|
||||
topcell.shapes (lindex2).insert (topcell.shapes (lindex1), db::ShapeIterator::Boxes);
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "box (1,2;3,4) #0\n");
|
||||
}
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "");
|
||||
|
||||
topcell.shapes (lindex2).insert (topcell.shapes (lindex1));
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "polygon (1,2;1,4;3,4;3,2) #0\nbox (1,2;3,4) #0\n");
|
||||
|
||||
{
|
||||
db::Transaction trans (&m, "T1");
|
||||
topcell.shapes (lindex2).clear (db::ShapeIterator::Polygons);
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), "box (1,2;3,4) #0\n");
|
||||
}
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string (_this, topcell.shapes (lindex2)), shapes_to_string (_this, topcell.shapes (lindex1)));
|
||||
}
|
||||
|
||||
TEST(10A)
|
||||
{
|
||||
if (db::default_editable_mode ()) {
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ std::string escape_xml_with_formatting (const std::string &s, bool &in_code)
|
|||
r += "<u>";
|
||||
} else if (sc.test ("@/u")) {
|
||||
r += "</u>";
|
||||
} else if (sc.test ("@tt")) {
|
||||
r += "<tt>";
|
||||
} else if (sc.test ("@/tt")) {
|
||||
r += "</tt>";
|
||||
} else if (sc.test ("@i")) {
|
||||
r += "<i>";
|
||||
} else if (sc.test ("@/i")) {
|
||||
|
|
|
|||
|
|
@ -1971,6 +1971,66 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def test_23
|
||||
|
||||
# layer operations with shape types
|
||||
|
||||
m = RBA::Manager::new
|
||||
|
||||
l = RBA::Layout.new(m)
|
||||
l1 = l.insert_layer(RBA::LayerInfo.new(1, 0))
|
||||
l2 = l.insert_layer(RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
||||
c0.shapes(l1).insert(RBA::Box::new(1, 2, 3, 4))
|
||||
c1.shapes(l1).insert(RBA::Polygon::new(RBA::Box::new(1, 2, 3, 4)))
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
m.transaction("T")
|
||||
l.clear_layer(l1, RBA::Shapes::SPolygons)
|
||||
m.commit
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:")
|
||||
|
||||
m.undo
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
m.transaction("T")
|
||||
l.move_layer(l1, l2, RBA::Shapes::SPolygons)
|
||||
m.commit
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:")
|
||||
|
||||
str2 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l2).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str2, "c0:\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
m.undo
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
str2 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l2).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str2, "c0:\nc1:")
|
||||
|
||||
m.transaction("T")
|
||||
l.copy_layer(l1, l2, RBA::Shapes::SPolygons)
|
||||
m.commit
|
||||
|
||||
str1 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l1).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str1, "c0:box (1,2;3,4)\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
str2 = l.each_cell.collect { |c| c.name + ":" + c.shapes(l2).each.collect { |sh| sh.to_s }.join(";") }.join("\n")
|
||||
assert_equal(str2, "c0:\nc1:polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
end
|
||||
|
||||
# Iterating while flatten
|
||||
def test_issue200
|
||||
|
||||
|
|
|
|||
|
|
@ -1595,6 +1595,34 @@ class DBShapes_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Shapes with shape-type specific insert and clear
|
||||
def test_11
|
||||
|
||||
s = RBA::Shapes::new
|
||||
s.insert(RBA::Box::new(1, 2, 3, 4))
|
||||
s.insert(RBA::Polygon::new(RBA::Box::new(1, 2, 3, 4)))
|
||||
|
||||
assert_equal(s.each.collect { |sh| sh.to_s }.join("; "), "polygon (1,2;1,4;3,4;3,2); box (1,2;3,4)")
|
||||
|
||||
s2 = RBA::Shapes::new
|
||||
s2.insert(s)
|
||||
|
||||
assert_equal(s2.each.collect { |sh| sh.to_s }.join("; "), "polygon (1,2;1,4;3,4;3,2); box (1,2;3,4)")
|
||||
|
||||
s2.clear(RBA::Shapes::SPolygons)
|
||||
|
||||
assert_equal(s2.each.collect { |sh| sh.to_s }.join("; "), "box (1,2;3,4)")
|
||||
|
||||
s2.clear
|
||||
|
||||
assert_equal(s2.each.collect { |sh| sh.to_s }.join("; "), "")
|
||||
|
||||
s2.insert(s, RBA::Shapes::SPolygons)
|
||||
|
||||
assert_equal(s2.each.collect { |sh| sh.to_s }.join("; "), "polygon (1,2;1,4;3,4;3,2)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue