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:
Matthias Koefferlein 2023-05-31 22:13:22 +02:00
parent 987bb005da
commit f11500996f
12 changed files with 414 additions and 47 deletions

View File

@ -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)
{

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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"

View File

@ -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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_overlapping (const db::Shapes *s, unsigned int flags, const db::Box &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_doverlapping (const db::Shapes *s, unsigned int flags, const db::DBox &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_overlapping_all (const db::Shapes *s, const db::Box &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_doverlapping_all (const db::Shapes *s, const db::DBox &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_touching (const db::Shapes *s, unsigned int flags, const db::Box &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_dtouching (const db::Shapes *s, unsigned int flags, const db::DBox &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_touching_all (const db::Shapes *s, const db::Box &region)
{
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 &region)
static gsi::layout_locking_iterator1<db::Shapes::shape_iterator> begin_dtouching_all (const db::Shapes *s, const db::DBox &region)
{
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"

View File

@ -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 ()) {

View File

@ -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")) {

View File

@ -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

View File

@ -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")