diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 1b228ab61..0d464e5f6 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -426,6 +426,33 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator return DeepLayer (this, layout_index, layer_index); } +DeepLayer DeepShapeStore::create_custom_layer (const db::RecursiveShapeIterator &si, HierarchyBuilderShapeReceiver *pipe, const db::ICplxTrans &trans) +{ + unsigned int layout_index = layout_for_iter (si, trans); + + db::Layout &layout = m_layouts[layout_index]->layout; + db::HierarchyBuilder &builder = m_layouts[layout_index]->builder; + + unsigned int layer_index = layout.insert_layer (); + builder.set_target_layer (layer_index); + + // Build the working hierarchy from the recursive shape iterator + try { + + tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy"))); + + builder.set_shape_receiver (pipe); + db::RecursiveShapeIterator (si).push (& builder); + builder.set_shape_receiver (0); + + } catch (...) { + builder.set_shape_receiver (0); + throw; + } + + return DeepLayer (this, layout_index, layer_index); +} + DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans) { unsigned int layout_index = layout_for_iter (si, trans); diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 0ea2bba60..b0958be42 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -285,6 +285,15 @@ public: */ DeepLayer create_edge_pair_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ()); + /** + * @brief Inserts a polygon layer into the deep shape store using a custom preparation pipeline + * + * This method will create a new layer inside the deep shapes store and + * feed it through the given pipeline. The pipeline may perform shape translations and + * finally will feed the target hierarchy. + */ + DeepLayer create_custom_layer (const db::RecursiveShapeIterator &si, HierarchyBuilderShapeReceiver *pipe, const ICplxTrans &trans = db::ICplxTrans ()); + /** * @brief Inserts the deep layer's shapes into some target layout */ diff --git a/src/db/db/dbOriginalLayerRegion.cc b/src/db/db/dbOriginalLayerRegion.cc index d481c5500..f796fa801 100644 --- a/src/db/db/dbOriginalLayerRegion.cc +++ b/src/db/db/dbOriginalLayerRegion.cc @@ -23,8 +23,13 @@ #include "dbOriginalLayerRegion.h" #include "dbFlatRegion.h" +#include "dbFlatEdges.h" #include "dbRegion.h" #include "dbShapeProcessor.h" +#include "dbDeepEdges.h" +#include "dbDeepRegion.h" +#include "dbDeepShapeStore.h" +#include "tlGlobPattern.h" namespace db { @@ -279,4 +284,165 @@ OriginalLayerRegion::ensure_merged_polygons_valid () const } } +namespace +{ + +template +struct dot_delivery +{ + typedef Container container_type; + + dot_delivery () + { + // .. nothing yet .. + } + + void insert (const db::Point &pt, Container *container) const + { + container->insert (db::Edge (pt, pt)); + } +}; + +template +struct box_delivery +{ + typedef Container container_type; + + box_delivery (db::Coord enl) + : m_d (enl, enl) + { + // .. nothing yet .. + } + + void insert (const db::Point &pt, Container *container) const + { + container->insert (db::Box (pt - m_d, pt + m_d)); + } + +private: + db::Vector m_d; +}; + +template +static void fill_texts (const Iter &iter, const std::string &pat, bool pattern, const Delivery &delivery, typename Delivery::container_type *container) +{ + tl::GlobPattern glob_pat; + bool all = false; + if (pattern) { + if (pat == "*") { + all = true; + } else { + glob_pat = tl::GlobPattern (pat); + } + } + + for (Iter si = iter; ! si.at_end (); ++si) { + if (si->is_text () && + (all || (pattern && glob_pat.match (si->text_string ())) || (!pattern && si->text_string () == pat))) { + db::Text t; + si->text (t); + t.transform (si.trans ()); + delivery.insert (t.box ().center (), container); + } + } +} + +template +class text_shape_receiver + : public db::HierarchyBuilderShapeReceiver +{ +public: + text_shape_receiver (const Delivery &delivery, const std::string &pat, bool pattern) + : m_delivery (delivery), m_glob_pat (), m_all (false), m_pattern (pattern), m_pat (pat) + { + if (pattern) { + if (m_pat == "*") { + m_all = true; + } else { + m_glob_pat = tl::GlobPattern (pat); + } + } + } + + virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) + { + if (shape.is_text () && + (m_all || (m_pattern && m_glob_pat.match (shape.text_string ())) || (!m_pattern && shape.text_string () == m_pat))) { + + db::Point pt = shape.bbox ().center (); + + if (! complex_region) { + if (region.contains (pt)) { + m_delivery.insert (pt.transformed (trans), target); + } + } else { + if (! complex_region->begin_overlapping (db::Box (pt, pt), db::box_convert ()).at_end ()) { + m_delivery.insert (pt.transformed (trans), target); + } + } + + } + } + + virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } + virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } + +private: + Delivery m_delivery; + tl::GlobPattern m_glob_pat; + bool m_all; + bool m_pattern; + std::string m_pat; +}; + +} + +db::EdgesDelegate * +OriginalLayerRegion::texts_as_dots (const std::string &pat, bool pattern) const +{ + db::RecursiveShapeIterator iter (m_iter); + iter.shape_flags (db::ShapeIterator::Texts); + + std::auto_ptr res (new db::FlatEdges ()); + res->set_merged_semantics (false); + + fill_texts (iter, pat, pattern, dot_delivery (), res.get ()); + + return res.release (); +} + +db::EdgesDelegate * +OriginalLayerRegion::texts_as_dots (const std::string &pat, bool pattern, db::DeepShapeStore &store) const +{ + db::RecursiveShapeIterator iter (m_iter); + iter.shape_flags (db::ShapeIterator::Texts); + + text_shape_receiver > pipe = text_shape_receiver > (dot_delivery (), pat, pattern); + return new db::DeepEdges (store.create_custom_layer (iter, &pipe)); +} + +db::RegionDelegate * +OriginalLayerRegion::texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl) const +{ + db::RecursiveShapeIterator iter (m_iter); + iter.shape_flags (db::ShapeIterator::Texts); + + std::auto_ptr res (new db::FlatRegion ()); + res->set_merged_semantics (false); + + fill_texts (iter, pat, pattern, box_delivery (enl), res.get ()); + + return res.release (); +} + +db::RegionDelegate * +OriginalLayerRegion::texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl, db::DeepShapeStore &store) const +{ + db::RecursiveShapeIterator iter (m_iter); + iter.shape_flags (db::ShapeIterator::Texts); + + text_shape_receiver > pipe = text_shape_receiver > (box_delivery (enl), pat, pattern); + return new db::DeepRegion (store.create_custom_layer (iter, &pipe)); +} + } diff --git a/src/db/db/dbOriginalLayerRegion.h b/src/db/db/dbOriginalLayerRegion.h index e8b2097bf..363e2f1ea 100644 --- a/src/db/db/dbOriginalLayerRegion.h +++ b/src/db/db/dbOriginalLayerRegion.h @@ -30,6 +30,10 @@ namespace db { +class EdgesDelegate; +class RegionDelegate; +class DeepShapeStore; + /** * @brief An original layerregion based on a RecursiveShapeIterator */ @@ -64,6 +68,11 @@ public: virtual bool equals (const Region &other) const; virtual bool less (const Region &other) const; + db::EdgesDelegate *texts_as_dots (const std::string &pat, bool pattern) const; + db::EdgesDelegate *texts_as_dots (const std::string &pat, bool pattern, db::DeepShapeStore &store) const; + db::RegionDelegate *texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl) const; + db::RegionDelegate *texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl, db::DeepShapeStore &store) const; + protected: virtual void merged_semantics_changed (); diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 0c4c83e57..1cf48d1cf 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -28,6 +28,7 @@ #include "dbEdgesUtils.h" #include "dbDeepEdges.h" #include "dbRegion.h" +#include "dbOriginalLayerRegion.h" #include "dbLayoutUtils.h" namespace gsi @@ -389,6 +390,17 @@ static bool is_deep (const db::Edges *e) return dynamic_cast (e->delegate ()) != 0; } +static db::Edges *new_texts_as_dots1 (const db::RecursiveShapeIterator &si, const std::string &pat, bool pattern) +{ + return new db::Edges (db::OriginalLayerRegion (si, false).texts_as_dots (pat, pattern)); +} + +static db::Edges *new_texts_as_dots2 (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const std::string &pat, bool pattern) +{ + return new db::Edges (db::OriginalLayerRegion (si, false).texts_as_dots (pat, pattern, dss)); +} + + Class dec_Edges ("db", "Edges", constructor ("new", &new_v, "@brief Default constructor\n" @@ -519,6 +531,47 @@ Class dec_Edges ("db", "Edges", "r = RBA::Edges::new(layout.begin_shapes(cell, layer), dss, RBA::ICplxTrans::new(layout.dbu / dbu), false)\n" "@/code\n" ) + + constructor ("new", &new_texts_as_dots1, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), + "@brief Constructor from a text set\n" + "\n" + "@param shape_iterator The iterator from which to derive the texts\n" + "@param expr The selection string\n" + "@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n" + "\n" + "This special constructor will create dot-like edges from the text objects delivered by the shape iterator. " + "Each text object will give a degenerated edge (a dot) that represents the text origin.\n" + "Texts can be selected by their strings - either through a glob pattern or by exact comparison with " + "the given string. The following options are available:\n" + "\n" + "@code\n" + "dots = RBA::Edges::new(iter, \"*\") # all texts\n" + "dots = RBA::Edges::new(iter, \"A*\") # all texts starting with an 'A'\n" + "dots = RBA::Edges::new(iter, \"A*\", false) # all texts exactly matchin 'A*'\n" + "@/code\n" + "\n" + "This method has been introduced in version 0.26.\n" + ) + + constructor ("new", &new_texts_as_dots2, gsi::arg("shape_iterator"), gsi::arg ("dss"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), + "@brief Constructor from a text set\n" + "\n" + "@param shape_iterator The iterator from which to derive the texts\n" + "@param dss The \\DeepShapeStore object that acts as a heap for hierarchical operations.\n" + "@param expr The selection string\n" + "@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n" + "\n" + "This special constructor will create a deep edge set from the text objects delivered by the shape iterator. " + "Each text object will give a degenerated edge (a dot) that represents the text origin.\n" + "Texts can be selected by their strings - either through a glob pattern or by exact comparison with " + "the given string. The following options are available:\n" + "\n" + "@code\n" + "region = RBA::Region::new(iter, dss, \"*\") # all texts\n" + "region = RBA::Region::new(iter, dss, \"A*\") # all texts starting with an 'A'\n" + "region = RBA::Region::new(iter, dss, \"A*\", false) # all texts exactly matchin 'A*'\n" + "@/code\n" + "\n" + "This method has been introduced in version 0.26.\n" + ) + method ("insert_into", &db::Edges::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"), "@brief Inserts this edge collection into the given layout, below the given cell and into the given layer.\n" "If the edge collection is a hierarchical one, a suitable hierarchy will be built below the top cell or " diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index e6da9e478..e55c1ba9d 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -25,6 +25,7 @@ #include "dbRegion.h" #include "dbRegionUtils.h" #include "dbDeepRegion.h" +#include "dbOriginalLayerRegion.h" #include "dbPolygonTools.h" #include "dbLayoutUtils.h" #include "dbShapes.h" @@ -77,77 +78,43 @@ static db::Region *new_shapes (const db::Shapes &s) return r; } -struct DotDelivery +static db::Region *new_texts_as_boxes1 (const db::RecursiveShapeIterator &si, const std::string &pat, bool pattern, db::Coord enl) { - typedef db::Edges container_type; - - DotDelivery () : container () - { - container.reset (new container_type ()); - container->set_merged_semantics (false); - } - - void insert (const db::Point &pt) - { - container->insert (db::Edge (pt, pt)); - } - - std::auto_ptr container; -}; - -struct BoxDelivery -{ - typedef db::Region container_type; - - BoxDelivery () : container () - { - container.reset (new container_type ()); - } - - void insert (const db::Point &pt) - { - container->insert (db::Box (pt - db::Vector (1, 1), pt + db::Vector (1, 1))); - } - - std::auto_ptr container; -}; - -template -static typename Delivery::container_type *new_texts (const db::RecursiveShapeIterator &si_in, const std::string &pat, bool pattern) -{ - db::RecursiveShapeIterator si (si_in); - si.shape_flags (db::ShapeIterator::Texts); - - tl::GlobPattern glob_pat; - bool all = false; - if (pattern) { - if (pat == "*") { - all = true; - } else { - glob_pat = tl::GlobPattern (pat); - } - } - - Delivery delivery; - - while (! si.at_end ()) { - if (si.shape ().is_text () && - (all || (pattern && glob_pat.match (si.shape ().text_string ())) || (!pattern && si.shape ().text_string () == pat))) { - db::Text t; - si.shape ().text (t); - t.transform (si.trans ()); - delivery.insert (t.box ().center ()); - } - si.next (); - } - - return delivery.container.release (); + return new db::Region (db::OriginalLayerRegion (si, false).texts_as_boxes (pat, pattern, enl)); } -template -static typename Delivery::container_type *texts (const db::Region *r, const std::string &pat, bool pattern) +static db::Region *new_texts_as_boxes2 (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const std::string &pat, bool pattern, db::Coord enl) { - return new_texts (r->iter (), pat, pattern); + return new db::Region (db::OriginalLayerRegion (si, false).texts_as_boxes (pat, pattern, enl, dss)); +} + +static const db::OriginalLayerRegion *org_layer (const db::Region *r) +{ + const db::OriginalLayerRegion *org_layer = dynamic_cast (r->delegate ()); + if (! org_layer) { + throw tl::Exception (tl::to_string (tr ("Texts can only be identified on an original layer"))); + } + return org_layer; +} + +static db::Edges *texts_as_dots1 (const db::Region *r, const std::string &pat, bool pattern) +{ + return new db::Edges (org_layer (r)->texts_as_dots (pat, pattern)); +} + +static db::Edges *texts_as_dots2 (const db::Region *r, db::DeepShapeStore &dss, const std::string &pat, bool pattern) +{ + return new db::Edges (org_layer (r)->texts_as_dots (pat, pattern, dss)); +} + +static db::Region *texts_as_boxes1 (const db::Region *r, const std::string &pat, bool pattern, db::Coord enl) +{ + return new db::Region (org_layer (r)->texts_as_boxes (pat, pattern, enl)); +} + +static db::Region *texts_as_boxes2 (const db::Region *r, db::DeepShapeStore &dss, const std::string &pat, bool pattern, db::Coord enl) +{ + return new db::Region (org_layer (r)->texts_as_boxes (pat, pattern, enl, dss)); } static db::Edges corners_to_dots (const db::Region *r, double angle_start, double angle_end) @@ -730,12 +697,13 @@ Class decl_Region ("db", "Region", "\n" "This method has been introduced in version 0.26.\n" ) + - constructor ("new", &new_texts, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), + constructor ("new", &new_texts_as_boxes1, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1), "@brief Constructor from a text set\n" "\n" "@param shape_iterator The iterator from which to derive the texts\n" "@param expr The selection string\n" "@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n" + "@param enl The per-side enlargement of the box to mark the text (1 gives a 2x2 DBU box)" "\n" "This special constructor will create a region from the text objects delivered by the shape iterator. " "Each text object will give a small (non-empty) box that represents the text origin.\n" @@ -748,7 +716,29 @@ Class decl_Region ("db", "Region", "region = RBA::Region::new(iter, \"A*\", false) # all texts exactly matchin 'A*'\n" "@/code\n" "\n" - "This method has been introduced in version 0.25." + "This method has been introduced in version 0.25. The enlargement parameter has been added in version 0.26.\n" + ) + + constructor ("new", &new_texts_as_boxes2, gsi::arg("shape_iterator"), gsi::arg ("dss"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1), + "@brief Constructor from a text set\n" + "\n" + "@param shape_iterator The iterator from which to derive the texts\n" + "@param dss The \\DeepShapeStore object that acts as a heap for hierarchical operations.\n" + "@param expr The selection string\n" + "@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n" + "@param enl The per-side enlargement of the box to mark the text (1 gives a 2x2 DBU box)" + "\n" + "This special constructor will create a deep region from the text objects delivered by the shape iterator. " + "Each text object will give a small (non-empty) box that represents the text origin.\n" + "Texts can be selected by their strings - either through a glob pattern or by exact comparison with " + "the given string. The following options are available:\n" + "\n" + "@code\n" + "region = RBA::Region::new(iter, dss, \"*\") # all texts\n" + "region = RBA::Region::new(iter, dss, \"A*\") # all texts starting with an 'A'\n" + "region = RBA::Region::new(iter, dss, \"A*\", false) # all texts exactly matchin 'A*'\n" + "@/code\n" + "\n" + "This variant has been introduced in version 0.26.\n" ) + method ("insert_into", &db::Region::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"), "@brief Inserts this region into the given layout, below the given cell and into the given layer.\n" @@ -757,11 +747,19 @@ Class decl_Region ("db", "Region", "\n" "This method has been introduced in version 0.26." ) + - factory_ext ("texts", &texts, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), + factory_ext ("texts", &texts_as_boxes1, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1), "@hide\n" "This method is provided for DRC implementation only." ) + - factory_ext ("texts_dots", &texts, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), + factory_ext ("texts", &texts_as_boxes2, gsi::arg ("dss"), gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1), + "@hide\n" + "This method is provided for DRC implementation only." + ) + + factory_ext ("texts_dots", &texts_as_dots1, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), + "@hide\n" + "This method is provided for DRC implementation only." + ) + + factory_ext ("texts_dots", &texts_as_dots2, gsi::arg ("dss"), gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), "@hide\n" "This method is provided for DRC implementation only." ) + diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 365fb797c..f439edf2a 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -30,6 +30,7 @@ #include "dbRegionProcessors.h" #include "dbEdgesUtils.h" #include "dbDeepShapeStore.h" +#include "dbOriginalLayerRegion.h" #include "tlUnitTest.h" #include "tlStream.h" @@ -1178,6 +1179,57 @@ TEST(22_TwoLayoutsWithDifferentDBU) db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au22.gds"); } +TEST(23_Texts) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l6 = ly.get_layer (db::LayerProperties (6, 1)); + unsigned int l8 = ly.get_layer (db::LayerProperties (8, 1)); + + db::Region r6boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_boxes ("*", true, 100, dss)); + db::Region r6dots; + db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_dots ("*", true, dss)).extended (r6dots, 20, 20, 20, 20); + db::Region r8boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_boxes ("VDD", false, 100, dss)); + db::Region r8dots; + db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_dots ("V*", true, dss)).extended (r8dots, 20, 20, 20, 20); + + db::Region rf6boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_boxes ("*", true, 100)); + db::Region rf6dots; + db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_dots ("*", true)).extended (rf6dots, 20, 20, 20, 20); + db::Region rf8boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_boxes ("VDD", false, 100)); + db::Region rf8dots; + db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_dots ("V*", true)).extended (rf8dots, 20, 20, 20, 20); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r6boxes); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r6dots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), rf6boxes); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rf6dots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r8boxes); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r8dots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), rf8boxes); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), rf8dots); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au23.gds"); + } +} + TEST(100_Integration) { db::Layout ly; diff --git a/testdata/algo/deep_region_au23.gds b/testdata/algo/deep_region_au23.gds new file mode 100644 index 000000000..2f0ab20d1 Binary files /dev/null and b/testdata/algo/deep_region_au23.gds differ diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index b8c9b7598..ec04f7d2d 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -786,6 +786,62 @@ class DBRegion_TestClass < TestBase end + # texts + def test_15 + + r = RBA::Region::new + ex = nil + begin + t = r.texts("*", true) + rescue => ex + end + assert_equal(ex.to_s, "Texts can only be identified on an original layer in Region::texts") + + r.insert(RBA::Box::new(1, 2, 3, 4)) + ex = nil + begin + t = r.texts("*", true) + rescue => ex + end + assert_equal(ex.to_s, "Texts can only be identified on an original layer in Region::texts") + + ly = RBA::Layout::new + top = ly.create_cell("TOP") + l1 = ly.layer(1, 0) + top.shapes(l1).insert(RBA::Text::new("ABC", RBA::Trans::new(RBA::Vector::new(100, 200)))) + + r = RBA::Region::new(top.begin_shapes_rec(l1)) + t = r.texts("*", true) + assert_equal(t.to_s, "(99,199;99,201;101,201;101,199)") + assert_equal(t.is_deep?, false) + t = r.texts("*", true, 10) + assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)") + t = r.texts("A*", true, 10) + assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)") + t = r.texts("A*", false, 10) + assert_equal(t.to_s, "") + t = r.texts("ABC", false, 10) + assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)") + + dss = RBA::DeepShapeStore::new + r = RBA::Region::new(top.begin_shapes_rec(l1)) + t = r.texts(dss, "*", true) + assert_equal(t.to_s, "(99,199;99,201;101,201;101,199)") + assert_equal(t.is_deep?, true) + + r = RBA::Region::new(top.begin_shapes_rec(l1)) + t = r.texts_dots("*", true) + assert_equal(t.to_s, "(100,200;100,200)") + assert_equal(t.is_deep?, false) + + dss = RBA::DeepShapeStore::new + r = RBA::Region::new(top.begin_shapes_rec(l1)) + t = r.texts_dots(dss, "A*", true) + assert_equal(t.to_s, "(100,200;100,200)") + assert_equal(t.is_deep?, true) + + end + # deep region tests def test_deep1