diff --git a/src/doc/doc/about/25d_screenshot2.png b/src/doc/doc/about/25d_screenshot2.png index 5c988166f4..eabf73fcff 100644 Binary files a/src/doc/doc/about/25d_screenshot2.png and b/src/doc/doc/about/25d_screenshot2.png differ diff --git a/src/doc/doc/about/25d_view.xml b/src/doc/doc/about/25d_view.xml index 22438889e8..1a33a8c5fe 100644 --- a/src/doc/doc/about/25d_view.xml +++ b/src/doc/doc/about/25d_view.xml @@ -171,19 +171,19 @@ end

-poly = input(2, 0)
-active = input(1, 0)
+gate = input(1, 0)
+active = input(2, 0)
 
-z(poly, zstart: 0, height: 20.nm, name: "POLY")
+z(active, zstart: 0, height: 20.nm, name: "ACTIVE")
 
-zz(name: "ACTIVE", like: "1/0") do
+zz(name: "GATE", like: "1/0") do
   
-  poly_sized = poly.sized(10.nm)
-  active_over_poly_sized = poly_sized & active
+  active_sized = active.sized(10.nm)
+  gate_over_active_sized = active_sized & gate
   
-  z(active - poly, zstart: 0, height: 10.nm)       # bottom sheet
-  z(active_over_poly_sized - poly, height: 10.nm)  # center sheet
-  z(active_over_poly_sized, height: 10.nm)         # top sheet
+  z(gate - active, zstart: 0, height: 10.nm)
+  z(gate_over_active_sized - active, height: 10.nm)
+  z(gate_over_active_sized, height: 10.nm)
 
 end
 
diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 53ac76a5a8..8aaa4341d1 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -1595,7 +1595,7 @@ def output_cell(cellname) if ! @def_output if @def_layout # establish a new default output from the default layout on this occasion - @def_output = LayoutOutputChannel::new(self, @def_layout, cellname.to_s, nil) + @def_output = LayoutOutputChannel::new(self, @def_layout, @def_layout.cell(cellname.to_s), nil) end else @def_output.cellname = cellname.to_s diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 74db2a3fa0..3851b72ecb 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1547,6 +1547,16 @@ TEST(60d_issue1216) run_test (_this, "60", true); } +TEST(61_issue1485) +{ + run_test (_this, "61", false); +} + +TEST(61d_issue1485) +{ + run_test (_this, "61", true); +} + TEST(70_props) { run_test (_this, "70", false); diff --git a/src/edt/edt/EditorOptionsGeneric.ui b/src/edt/edt/EditorOptionsGeneric.ui index 8de52d0097..84c102c717 100644 --- a/src/edt/edt/EditorOptionsGeneric.ui +++ b/src/edt/edt/EditorOptionsGeneric.ui @@ -95,10 +95,30 @@ 2 - - + + + + + 0 + 0 + + + + Enter the grid in micron. Can be anisotropic ("gx,gy") + + + + + - Grid + Objects + + + + + + + Snap to other objects @@ -130,17 +150,10 @@ - - - - Snap to other objects - - - - - + + - Objects + Grid @@ -157,16 +170,10 @@ - - - - - 0 - 0 - - - - Enter the grid in micron. Can be anisotropic ("gx,gy") + + + + Snap to grid while moving diff --git a/src/edt/edt/edtConfig.cc b/src/edt/edt/edtConfig.cc index 8c158130ea..50be8b6c58 100644 --- a/src/edt/edt/edtConfig.cc +++ b/src/edt/edt/edtConfig.cc @@ -32,6 +32,7 @@ namespace edt std::string cfg_edit_grid ("edit-grid"); std::string cfg_edit_snap_to_objects ("edit-snap-to-objects"); +std::string cfg_edit_snap_objects_to_grid ("edit-snap-objects-to-grid"); std::string cfg_edit_move_angle_mode ("edit-move-angle-mode"); std::string cfg_edit_connect_angle_mode ("edit-connect-angle-mode"); std::string cfg_edit_text_string ("edit-text-string"); diff --git a/src/edt/edt/edtConfig.h b/src/edt/edt/edtConfig.h index 6a8ce403a5..36862a8ea2 100644 --- a/src/edt/edt/edtConfig.h +++ b/src/edt/edt/edtConfig.h @@ -40,6 +40,7 @@ namespace edt */ extern EDT_PUBLIC std::string cfg_edit_grid; extern EDT_PUBLIC std::string cfg_edit_snap_to_objects; +extern EDT_PUBLIC std::string cfg_edit_snap_objects_to_grid; extern EDT_PUBLIC std::string cfg_edit_move_angle_mode; extern EDT_PUBLIC std::string cfg_edit_connect_angle_mode; extern EDT_PUBLIC std::string cfg_edit_text_string; diff --git a/src/edt/edt/edtEditorOptionsPages.cc b/src/edt/edt/edtEditorOptionsPages.cc index e7d23954d8..74a364b5b9 100644 --- a/src/edt/edt/edtEditorOptionsPages.cc +++ b/src/edt/edt/edtEditorOptionsPages.cc @@ -85,6 +85,7 @@ EditorOptionsGeneric::EditorOptionsGeneric (lay::LayoutViewBase *view, lay::Disp connect (mp_ui->hier_sel_cbx, SIGNAL (clicked ()), this, SLOT (edited ())); connect (mp_ui->hier_copy_mode_cbx, SIGNAL (activated (int)), this, SLOT (edited ())); connect (mp_ui->snap_objects_cbx, SIGNAL (clicked ()), this, SLOT (edited ())); + connect (mp_ui->snap_objects_to_grid_cbx, SIGNAL (clicked ()), this, SLOT (edited ())); connect (mp_ui->max_shapes_le, SIGNAL (editingFinished ()), this, SLOT (edited ())); connect (mp_ui->show_shapes_cbx, SIGNAL (clicked ()), this, SLOT (edited ())); } @@ -132,6 +133,7 @@ EditorOptionsGeneric::apply (lay::Dispatcher *root) int cpm = mp_ui->hier_copy_mode_cbx->currentIndex (); root->config_set (cfg_edit_hier_copy_mode, tl::to_string ((cpm < 0 || cpm > 1) ? -1 : cpm)); root->config_set (cfg_edit_snap_to_objects, tl::to_string (mp_ui->snap_objects_cbx->isChecked ())); + root->config_set (cfg_edit_snap_objects_to_grid, tl::to_string (mp_ui->snap_objects_to_grid_cbx->isChecked ())); configure_from_line_edit (root, mp_ui->max_shapes_le, cfg_edit_max_shapes_of_instances); root->config_set (cfg_edit_show_shapes_of_instances, tl::to_string (mp_ui->show_shapes_cbx->isChecked ())); @@ -194,6 +196,10 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root) root->config_get (cfg_edit_snap_to_objects, snap_to_objects); mp_ui->snap_objects_cbx->setChecked (snap_to_objects); + bool snap_objects_to_grid = false; + root->config_get (cfg_edit_snap_objects_to_grid, snap_objects_to_grid); + mp_ui->snap_objects_to_grid_cbx->setChecked (snap_objects_to_grid); + unsigned int max_shapes = 1000; root->config_get (cfg_edit_max_shapes_of_instances, max_shapes); mp_ui->max_shapes_le->setText (tl::to_qstring (tl::to_string (max_shapes))); diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 368ddaa394..565dbb24fa 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -1102,6 +1102,7 @@ PartialService::PartialService (db::Manager *manager, lay::LayoutViewBase *view, m_buttons (0), m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global), m_snap_to_objects (true), + m_snap_objects_to_grid (true), m_top_level_sel (false), m_hover (false), m_hover_wait (false), @@ -1341,6 +1342,9 @@ PartialService::configure (const std::string &name, const std::string &value) } else if (name == cfg_edit_snap_to_objects) { tl::from_string (value, m_snap_to_objects); return true; // taken + } else if (name == cfg_edit_snap_objects_to_grid) { + tl::from_string (value, m_snap_objects_to_grid); + return true; // taken } else if (name == cfg_edit_move_angle_mode) { acc.from_string (value, m_move_ac); return true; // taken @@ -1651,7 +1655,7 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo // thus, we can bring the point on grid or to an object's edge or vertex snap_details = snap2 (p); if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); } else { m_current = snap_details.snapped_point; mouse_cursor_from_snap_details (snap_details); @@ -1660,7 +1664,7 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo } else { // snap movement to angle and grid without object - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); clear_mouse_cursors (); } @@ -2198,9 +2202,86 @@ PartialService::begin_move (MoveMode mode, const db::DPoint &p, lay::angle_const } } +void +PartialService::update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const +{ + db::DVector v = snap (pt) - pt; + + if (! result_set || v.length () < vr.length ()) { + result_set = true; + vr = v; + } +} + +db::DVector +PartialService::snap_marker_to_grid (const db::DVector &v, bool &snapped) const +{ + if (! m_snap_objects_to_grid) { + return v; + } + + snapped = false; + db::DVector vr; + + // max. 10000 checks + size_t count = 10000; + + db::DVector snapped_to (1.0, 1.0); + db::DVector vv = lay::snap_angle (v, move_ac (), &snapped_to); + + TransformationVariants tv (view ()); + + for (auto r = m_selection.begin (); r != m_selection.end (); ++r) { + + if (! r->first.is_valid (view ()) || r->first.is_cell_inst ()) { + continue; + } + + const lay::CellView &cv = view ()->cellview (r->first.cv_index ()); + const std::vector *tv_list = tv.per_cv_and_layer (r->first.cv_index (), r->first.layer ()); + if (!tv_list || tv_list->empty ()) { + continue; + } + + db::CplxTrans tr = db::DCplxTrans (vv) * tv_list->front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans () * r->first.trans (); + + for (auto e = r->second.begin (); e != r->second.end () && count > 0; ++e) { + update_vector_snapped_point (tr * e->p1 (), vr, snapped); + --count; + if (count > 0) { + update_vector_snapped_point (tr * e->p2 (), vr, snapped); + --count; + } + } + + } + + if (snapped) { + vr += vv; + return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ()); + } else { + return db::DVector (); + } +} + +db::DVector +PartialService::snap_move (const db::DVector &v) const +{ + bool snapped = false; + db::DVector vs = snap_marker_to_grid (v, snapped); + if (! snapped) { + vs = snap (v); + } + return vs; +} + void PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) { + if (! m_dragging) { + return; + } + m_alt_ac = ac; set_cursor (lay::Cursor::size_all); @@ -2214,7 +2295,7 @@ PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) // thus, we can bring the point on grid or to an object's edge or vertex snap_details = snap2 (p); if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); } else { m_current = snap_details.snapped_point; mouse_cursor_from_snap_details (snap_details); @@ -2223,7 +2304,7 @@ PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) } else { // snap movement to angle and grid without object - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); clear_mouse_cursors (); } @@ -2236,6 +2317,10 @@ PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) void PartialService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type ac) { + if (! m_dragging) { + return; + } + m_alt_ac = ac; if (m_current != m_start) { diff --git a/src/edt/edt/edtPartialService.h b/src/edt/edt/edtPartialService.h index cdc07b61dc..113cac0f5b 100644 --- a/src/edt/edt/edtPartialService.h +++ b/src/edt/edt/edtPartialService.h @@ -341,6 +341,7 @@ public slots: lay::angle_constraint_type m_connect_ac, m_move_ac, m_alt_ac; db::DVector m_edit_grid; bool m_snap_to_objects; + bool m_snap_objects_to_grid; db::DVector m_global_grid; bool m_top_level_sel; @@ -373,6 +374,9 @@ public slots: db::DPoint snap (const db::DPoint &p) const; db::DVector snap (const db::DVector &p) const; lay::PointSnapToObjectResult snap2 (const db::DPoint &p) const; + void update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const; + db::DVector snap_marker_to_grid (const db::DVector &v, bool &snapped) const; + db::DVector snap_move(const db::DVector &p) const; void enter_edge (const EdgeWithIndex &e, size_t &nmarker, partial_objects::const_iterator sel, const std::map &new_points, const std::map &new_edges, const db::ICplxTrans >, const std::vector &tv, bool transient); void enter_vertices (size_t &nmarker, partial_objects::const_iterator sel, const std::map &new_points, const std::map &new_edges, const db::ICplxTrans >, const std::vector &tv, bool transient); diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index d9e374902f..a23055a27b 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -331,6 +331,7 @@ class MainPluginDeclaration options.push_back (std::pair (cfg_edit_hier_copy_mode, "-1")); options.push_back (std::pair (cfg_edit_grid, "")); options.push_back (std::pair (cfg_edit_snap_to_objects, "false")); + options.push_back (std::pair (cfg_edit_snap_objects_to_grid, "true")); options.push_back (std::pair (cfg_edit_move_angle_mode, "any")); options.push_back (std::pair (cfg_edit_connect_angle_mode, "any")); options.push_back (std::pair (cfg_edit_combine_mode, "add")); diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index d2bb74075a..5d415b9b5d 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -72,7 +72,8 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter m_flags (flags), m_move_sel (false), m_moving (false), m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global), - m_snap_to_objects (false), + m_snap_to_objects (true), + m_snap_objects_to_grid (true), m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000), m_hier_copy_mode (-1), m_indicate_secondary_selection (false), @@ -94,6 +95,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view) m_move_sel (false), m_moving (false), m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global), m_snap_to_objects (true), + m_snap_objects_to_grid (true), m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000), m_hier_copy_mode (-1), m_indicate_secondary_selection (false), @@ -148,6 +150,123 @@ Service::snap (db::DPoint p) const return p; } +void +Service::update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const +{ + db::DVector v = snap (pt) - pt; + + if (! result_set || v.length () < vr.length ()) { + result_set = true; + vr = v; + } +} + +void +Service::update_vector_snapped_marker (const lay::ShapeMarker *sm, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const +{ + const db::Shape &shape = sm->shape (); + db::CplxTrans tr = db::DCplxTrans (trans) * db::DCplxTrans (-sm->trans ().disp ()) * sm->trans (); + + if (shape.is_text ()) { + + update_vector_snapped_point (tr * shape.bbox ().center (), vr, result_set); + --count; + + } else if (shape.is_point ()) { + + update_vector_snapped_point (tr * shape.point (), vr, result_set); + --count; + + } else if (shape.is_edge ()) { + + update_vector_snapped_point (tr * shape.edge ().p1 (), vr, result_set); + --count; + if (count > 0) { + update_vector_snapped_point (tr * shape.edge ().p2 (), vr, result_set); + --count; + } + + } else if (shape.is_path ()) { + + for (auto pt = shape.begin_point (); pt != shape.end_point () && count > 0; ++pt) { + update_vector_snapped_point (tr * *pt, vr, result_set); + --count; + } + + } else if (shape.is_box ()) { + + db::Box box = shape.bbox (); + for (unsigned int c = 0; c < 4 && count > 0; ++c) { + db::Point pt = db::Point ((c & 1) != 0 ? box.left () : box.right (), (c & 2) != 0 ? box.bottom () : box.top ()); + update_vector_snapped_point (tr * pt, vr, result_set); + --count; + } + + } else if (shape.is_polygon ()) { + + for (auto pt = shape.begin_hull (); pt != shape.end_hull () && count > 0; ++pt) { + update_vector_snapped_point (tr * *pt, vr, result_set); + --count; + } + + for (unsigned int h = 0; h < shape.holes () && count > 0; ++h) { + for (auto pt = shape.begin_hole (h); pt != shape.end_hole (h) && count > 0; ++pt) { + update_vector_snapped_point (tr * *pt, vr, result_set); + --count; + } + } + + } +} + +void +Service::update_vector_snapped_marker (const lay::InstanceMarker *im, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const +{ + const db::Instance &instance = im->instance (); + db::CplxTrans tr = db::DCplxTrans (trans) * db::DCplxTrans (-im->trans ().disp ()) * im->trans (); + + update_vector_snapped_point (tr * (instance.complex_trans () * db::Point ()), vr, result_set); + --count; +} + +db::DVector +Service::snap_marker_to_grid (const db::DVector &v, bool &snapped) const +{ + if (! m_snap_objects_to_grid) { + return v; + } + + snapped = false; + db::DVector vr; + + // max. 10000 checks + size_t count = 10000; + + db::DVector snapped_to (1.0, 1.0); + db::DVector vv = lay::snap_angle (v, move_ac (), &snapped_to); + + db::DTrans tt = db::DTrans (vv); + + for (auto m = m_markers.begin (); m != m_markers.end () && count > 0; ++m) { + + const lay::ShapeMarker *sm = dynamic_cast (*m); + const lay::InstanceMarker *im = dynamic_cast (*m); + if (sm) { + update_vector_snapped_marker (sm, tt, vr, snapped, count); + } else if (im) { + update_vector_snapped_marker (im, tt, vr, snapped, count); + } + + } + + if (snapped) { + vr += vv; + return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ()); + } else { + return db::DVector (); + } +} + db::DVector Service::snap (db::DVector v) const { @@ -239,6 +358,13 @@ Service::configure (const std::string &name, const std::string &value) return true; // taken + } else if (name == cfg_edit_snap_objects_to_grid) { + + tl::from_string (value, m_snap_objects_to_grid); + service_configuration_changed (); + + return true; // taken + } else if (name == cfg_edit_move_angle_mode) { acc.from_string (value, m_move_ac); @@ -434,9 +560,14 @@ void Service::move (const db::DPoint &pu, lay::angle_constraint_type ac) { m_alt_ac = ac; - db::DPoint p = snap (m_move_start) + snap (pu - m_move_start, false /*move*/); if (view ()->is_editable () && m_moving) { - move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - snap (m_move_start))); + db::DPoint ref = snap (m_move_start); + bool snapped = false; + db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped); + if (! snapped) { + p = ref + snap (pu - m_move_start, false /*move*/); + } + move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref)); } m_alt_ac = lay::AC_Global; } @@ -445,9 +576,14 @@ void Service::move_transform (const db::DPoint &pu, db::DFTrans tr, lay::angle_constraint_type ac) { m_alt_ac = ac; - db::DPoint p = snap (m_move_start) + snap (pu - m_move_start, false); if (view ()->is_editable () && m_moving) { - move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (m_move_trans.fp_trans () * tr) * db::DTrans (db::DPoint () - snap (m_move_start))); + db::DPoint ref = snap (m_move_start); + bool snapped = false; + db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped); + if (! snapped) { + p = ref + snap (pu - m_move_start, false /*move*/); + } + move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (tr * m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref)); } m_alt_ac = lay::AC_Global; } diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h index 14e16c22fc..bc09bed4b2 100644 --- a/src/edt/edt/edtService.h +++ b/src/edt/edt/edtService.h @@ -518,6 +518,14 @@ class EDT_PUBLIC Service */ db::DVector snap (const db::DVector &v, bool connect) const; + /** + * @brief Proposes a grid-snapped displacement vector + * + * @param v The input displacement + * @return A displacement that pushes the (current) markers on-grid, definition depending on marker + */ + db::DVector snap_marker_to_grid (const db::DVector &v, bool &snapped) const; + /** * @brief Snap a point to the edit grid with advanced snapping (including object snapping) * @@ -605,6 +613,7 @@ class EDT_PUBLIC Service lay::angle_constraint_type m_connect_ac, m_move_ac, m_alt_ac; db::DVector m_edit_grid; bool m_snap_to_objects; + bool m_snap_objects_to_grid; db::DVector m_global_grid; bool m_top_level_sel; bool m_show_shapes_of_instances; @@ -658,6 +667,9 @@ class EDT_PUBLIC Service private: void copy_selected (unsigned int inst_mode); + void update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const; + void update_vector_snapped_marker (const lay::ShapeMarker *sm, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const; + void update_vector_snapped_marker (const lay::InstanceMarker *sm, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const; }; } diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index b4309db4ae..e7c54f7687 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -817,10 +817,8 @@ ApplicationBase::init_app () } } - std::set already_executed; - // run all early autorun macros - lym::MacroCollection::root ().autorun_early (&already_executed); + lym::MacroCollection::root ().autorun_early (); // redo gsi::initialize as the macros may have registered new external classes // through the "doc to external class" mechanism. @@ -833,7 +831,7 @@ ApplicationBase::init_app () // as this regenerates the macro collection, autorun_early is required again // note: this does no re-execute macros that have been executed already - lym::MacroCollection::root ().autorun_early (&already_executed); + lym::MacroCollection::root ().autorun_early (); } @@ -842,7 +840,7 @@ ApplicationBase::init_app () lym::MacroCollection::root ().rescan (); // and yet another autorun_early pass .. - lym::MacroCollection::root ().autorun_early (&already_executed); + lym::MacroCollection::root ().autorun_early (); // creates the main window or plugin root as required setup (); diff --git a/src/laybasic/laybasic/layMarker.h b/src/laybasic/laybasic/layMarker.h index d807dbf24b..3fa54b4427 100644 --- a/src/laybasic/laybasic/layMarker.h +++ b/src/laybasic/laybasic/layMarker.h @@ -396,6 +396,14 @@ class LAYBASIC_PUBLIC ShapeMarker */ void set (const db::Shape &shape, const db::ICplxTrans &t1, const std::vector &trans); + /** + * @brief Gets the shape + */ + const db::Shape &shape () const + { + return m_shape; + } + private: virtual void render (const Viewport &vp, ViewObjectCanvas &canvas); @@ -431,6 +439,14 @@ class LAYBASIC_PUBLIC InstanceMarker */ ~InstanceMarker (); + /** + * @brief Gets the instance + */ + const db::Instance &instance () const + { + return m_inst; + } + /** * @brief Set the instance the marker is to display * diff --git a/src/laybasic/laybasic/laySnap.cc b/src/laybasic/laybasic/laySnap.cc index b6d268b328..d04f9395bb 100644 --- a/src/laybasic/laybasic/laySnap.cc +++ b/src/laybasic/laybasic/laySnap.cc @@ -183,7 +183,7 @@ draw_round_dbl (const db::DPoint &p1, const db::DPoint &p2, int /*h*/) } db::DVector -snap_angle (const db::DVector &in, lay::angle_constraint_type ac) +snap_angle (const db::DVector &in, lay::angle_constraint_type ac, db::DVector *snapped_to) { std::vector ref_dir; if (ac != lay::AC_Any) { @@ -206,11 +206,17 @@ snap_angle (const db::DVector &in, lay::angle_constraint_type ac) proj = db::sprod (*re, in) / (elen * re->length ()); if (proj > max_proj) { max_proj = proj; + if (snapped_to) { + *snapped_to = *re; + } out = *re * (elen * proj / re->length ()); } proj = db::sprod (-*re, in) / (elen * re->length ()); if (proj > max_proj) { max_proj = proj; + if (snapped_to) { + *snapped_to = *re; + } out = -*re * (elen * proj / re->length ()); } } @@ -218,6 +224,7 @@ snap_angle (const db::DVector &in, lay::angle_constraint_type ac) return out; } + // --------------------------------------------------------------------------------------- // obj_snap implementations diff --git a/src/laybasic/laybasic/laySnap.h b/src/laybasic/laybasic/laySnap.h index 6ac05fc685..bb22a2be95 100644 --- a/src/laybasic/laybasic/laySnap.h +++ b/src/laybasic/laybasic/laySnap.h @@ -238,8 +238,12 @@ namespace lay /** * @brief Reduce a given vector according to the angle constraint + * + * If the "snapped_to" pointer is non-null, it will receive the snap target + * vector (e.g. (1, 0) for snapping to horizontal axis. If no snapping happens, + * the value of this vector is not changed. */ - LAYBASIC_PUBLIC db::DVector snap_angle (const db::DVector &in, lay::angle_constraint_type ac); + LAYBASIC_PUBLIC db::DVector snap_angle (const db::DVector &in, lay::angle_constraint_type ac, db::DVector *snapped_to = 0); /** * @brief rounding of a double value for drawing purposes diff --git a/src/lym/lym/lymMacro.cc b/src/lym/lym/lymMacro.cc index ac179c0ea3..e6884cce1b 100644 --- a/src/lym/lym/lymMacro.cc +++ b/src/lym/lym/lymMacro.cc @@ -55,7 +55,10 @@ namespace lym // ---------------------------------------------------------------------- Macro::Macro () - : m_modified (true), m_readonly (false), m_autorun (false), m_autorun_default (false), m_autorun_early (false), m_priority (0), m_show_in_menu (false), m_is_file (false), m_interpreter (None), m_format (Macro::NoFormat) + : m_modified (true), m_readonly (false), + m_autorun (false), m_autorun_default (false), m_autorun_early (false), m_was_autorun (false), + m_priority (0), m_show_in_menu (false), m_is_file (false), + m_interpreter (None), m_format (Macro::NoFormat) { mp_parent = 0; } @@ -70,6 +73,8 @@ void Macro::on_menu_needs_update () void Macro::on_changed () { + m_was_autorun = false; + #if defined(HAVE_QT) emit changed (); if (mp_parent) { @@ -796,6 +801,11 @@ void Macro::set_autorun (bool f) } } +void Macro::set_was_autorun (bool f) +{ + m_was_autorun = f; +} + void Macro::set_priority (int p) { if (p != m_priority) { diff --git a/src/lym/lym/lymMacro.h b/src/lym/lym/lymMacro.h index 10acb6f362..88af3159dd 100644 --- a/src/lym/lym/lymMacro.h +++ b/src/lym/lym/lymMacro.h @@ -426,6 +426,19 @@ Q_OBJECT return m_autorun_early; } + /** + * @brief Sets a value indicating whether the macro was alread auto-runned + */ + void set_was_autorun (bool f); + + /** + * @brief Gets a value indicating whether the macro was alread auto-runned + */ + bool was_autorun () const + { + return m_was_autorun; + } + /** * @brief Sets a value indicating whether the macro shall be executed on startup */ @@ -618,6 +631,7 @@ Q_OBJECT bool m_autorun; bool m_autorun_default; bool m_autorun_early; + bool m_was_autorun; int m_priority; bool m_show_in_menu; std::string m_group_name; diff --git a/src/lym/lym/lymMacroCollection.cc b/src/lym/lym/lymMacroCollection.cc index 6712d6549a..4982ae1922 100644 --- a/src/lym/lym/lymMacroCollection.cc +++ b/src/lym/lym/lymMacroCollection.cc @@ -868,7 +868,7 @@ static bool has_autorun_for (const lym::MacroCollection &collection, bool early) } for (lym::MacroCollection::const_iterator c = collection.begin (); c != collection.end (); ++c) { - if ((early && c->second->is_autorun_early ()) || (!early && c->second->is_autorun () && !c->second->is_autorun_early ())) { + if (((early && c->second->is_autorun_early ()) || (!early && c->second->is_autorun () && !c->second->is_autorun_early ())) && ! c->second->was_autorun ()) { return true; } } @@ -909,35 +909,28 @@ static int collect_priority (lym::MacroCollection &collection, bool early, int f return p; } -static void autorun_for_prio (lym::MacroCollection &collection, bool early, std::set *executed_already, int prio) +static void autorun_for_prio (lym::MacroCollection &collection, bool early, int prio) { for (lym::MacroCollection::child_iterator c = collection.begin_children (); c != collection.end_children (); ++c) { - autorun_for_prio (*c->second, early, executed_already, prio); + autorun_for_prio (*c->second, early, prio); } for (lym::MacroCollection::iterator c = collection.begin (); c != collection.end (); ++c) { - if (c->second->priority () == prio && c->second->can_run () && ((early && c->second->is_autorun_early ()) || (!early && c->second->is_autorun () && !c->second->is_autorun_early ()))) { + if (! c->second->was_autorun () && c->second->priority () == prio && c->second->can_run () && ((early && c->second->is_autorun_early ()) || (!early && c->second->is_autorun () && !c->second->is_autorun_early ()))) { - if (!executed_already || executed_already->find (c->second->path ()) == executed_already->end ()) { - - BEGIN_PROTECTED_SILENT - c->second->run (); - c->second->install_doc (); - END_PROTECTED_SILENT - - if (executed_already) { - executed_already->insert (c->second->path ()); - } - - } + BEGIN_PROTECTED_SILENT + c->second->run (); + c->second->set_was_autorun (true); + c->second->install_doc (); + END_PROTECTED_SILENT } } } -static void autorun_for (lym::MacroCollection &collection, bool early, std::set *executed_already) +static void autorun_for (lym::MacroCollection &collection, bool early) { int prio = 0; while (true) { @@ -945,19 +938,19 @@ static void autorun_for (lym::MacroCollection &collection, bool early, std::set< if (p < prio) { break; } - autorun_for_prio (collection, early, executed_already, p); + autorun_for_prio (collection, early, p); prio = p + 1; } } -void MacroCollection::autorun (std::set *already_executed) +void MacroCollection::autorun () { - autorun_for (*this, false, already_executed); + autorun_for (*this, false); } -void MacroCollection::autorun_early (std::set *already_executed) +void MacroCollection::autorun_early () { - autorun_for (*this, true, already_executed); + autorun_for (*this, true); } void MacroCollection::dump (int l) diff --git a/src/lym/lym/lymMacroCollection.h b/src/lym/lym/lymMacroCollection.h index 60c779bc5c..427f682626 100644 --- a/src/lym/lym/lymMacroCollection.h +++ b/src/lym/lym/lymMacroCollection.h @@ -419,7 +419,7 @@ Q_OBJECT /** * @brief Runs all macros marked with auto-run */ - void autorun (std::set *already_executed = 0); + void autorun (); /** * @brief Returns true, if the collection has an early autorun macro @@ -429,7 +429,7 @@ Q_OBJECT /** * @brief Runs all macros marked with early auto-run */ - void autorun_early (std::set *already_executed = 0); + void autorun_early (); /** * @brief Redo the scan (will add new files or folders) diff --git a/testdata/drc/drcSimpleTests_61.drc b/testdata/drc/drcSimpleTests_61.drc new file mode 100644 index 0000000000..35c3d7043c --- /dev/null +++ b/testdata/drc/drcSimpleTests_61.drc @@ -0,0 +1,23 @@ + +# Moved implementation + +source($drc_test_source) +target($drc_test_target) + +if $drc_test_deep + deep +end + +input(1, 0).output(1, 0) +input(2, 0).output(2, 0) + +cell("TOP") + +l1 = input(1, 0) +l2 = input(2, 0) + +l1.output(10, 0) +l2.output(11, 0) +l1.sized(100.nm).output(20, 0) +(l2 - l1).output(21, 0) + diff --git a/testdata/drc/drcSimpleTests_61.gds b/testdata/drc/drcSimpleTests_61.gds new file mode 100644 index 0000000000..ce30bc4750 Binary files /dev/null and b/testdata/drc/drcSimpleTests_61.gds differ diff --git a/testdata/drc/drcSimpleTests_au61.gds b/testdata/drc/drcSimpleTests_au61.gds new file mode 100644 index 0000000000..fc3a059a00 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au61.gds differ diff --git a/testdata/drc/drcSimpleTests_au61d.gds b/testdata/drc/drcSimpleTests_au61d.gds new file mode 100644 index 0000000000..06538e9c17 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au61d.gds differ