From 6e4ac714421dc45902ff795572c8c42f415e6a0e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 23:48:34 +0200 Subject: [PATCH 1/2] WIP --- src/db/db/dbPCellVariant.cc | 20 +- src/edt/edt/PointPropertiesPage.ui | 282 ++++++++++++++++++ src/edt/edt/edt.pro | 3 + src/edt/edt/edtMainService.cc | 2 + src/edt/edt/edtPartialService.cc | 3 + src/edt/edt/edtPlugin.cc | 14 +- src/edt/edt/edtPlugin.h | 1 + src/edt/edt/edtPropertiesPageUtils.cc | 36 +++ src/edt/edt/edtPropertiesPageUtils.h | 16 + src/edt/edt/edtPropertiesPages.cc | 118 ++++++++ src/edt/edt/edtPropertiesPages.h | 29 ++ src/edt/edt/edtServiceImpl.cc | 111 +++++++ src/edt/edt/edtServiceImpl.h | 28 ++ src/edt/edt/edtUtils.cc | 18 +- src/laybasic/laybasic/layBitmapRenderer.cc | 4 +- .../laybasic/layRedrawThreadWorker.cc | 4 +- src/laybasic/laybasic/layRenderer.cc | 2 + 17 files changed, 666 insertions(+), 25 deletions(-) create mode 100644 src/edt/edt/PointPropertiesPage.ui diff --git a/src/db/db/dbPCellVariant.cc b/src/db/db/dbPCellVariant.cc index 8f46f2199..e5660daf0 100644 --- a/src/db/db/dbPCellVariant.cc +++ b/src/db/db/dbPCellVariant.cc @@ -199,51 +199,51 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (db::Box (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (db::Edge (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::DPoint p = m_parameters[i].to_user (); - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (db::Point (p * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::Point p = m_parameters[i].to_user (); - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (p, p), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (p, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); db::Polygon poly = m_parameters[i].to_user ().transformed (dbu_trans, false); // Hint: we don't compress the polygon since we don't want to loose information - shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::Polygon poly = m_parameters[i].to_user (); // Hint: we don't compress the polygon since we don't want to loose information - shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); - shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (dbu_trans * m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } diff --git a/src/edt/edt/PointPropertiesPage.ui b/src/edt/edt/PointPropertiesPage.ui new file mode 100644 index 000000000..325d018b9 --- /dev/null +++ b/src/edt/edt/PointPropertiesPage.ui @@ -0,0 +1,282 @@ + + + PointPropertiesPage + + + + 0 + 0 + 531 + 370 + + + + Form + + + + 6 + + + 9 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + + + + Sans Serif + 12 + false + true + false + false + + + + Point Properties + + + + + + + + 0 + 0 + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Point position + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 6 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + x = + + + + + + + + 1 + 0 + + + + + + + + y = + + + + + + + + 1 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 478 + 10 + + + + + + + + Coordinates in database units + + + + + + + Absolute (accumulated) transformations + + + + + + + Qt::Vertical + + + + 478 + 16 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 211 + 20 + + + + + + + + User Properties + + + + + + + Instantiation + + + + + + + + + + dbu_cb + abs_cb + prop_pb + inst_pb + + + + diff --git a/src/edt/edt/edt.pro b/src/edt/edt/edt.pro index 7680a9946..477e14ff4 100644 --- a/src/edt/edt/edt.pro +++ b/src/edt/edt/edt.pro @@ -92,3 +92,6 @@ LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_laybasic -lklayout_layv } +FORMS += \ + PointPropertiesPage.ui + diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index b1f4b2df5..6f9be9888 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -2537,6 +2537,7 @@ public: { mp_polygon_service = view->get_plugin (); mp_box_service = view->get_plugin (); + mp_point_service = view->get_plugin (); mp_text_service = view->get_plugin (); mp_path_service = view->get_plugin (); mp_inst_service = view->get_plugin (); @@ -2587,6 +2588,7 @@ public: private: edt::PolygonService *mp_polygon_service; edt::BoxService *mp_box_service; + edt::PointService *mp_point_service; edt::TextService *mp_text_service; edt::PathService *mp_path_service; edt::InstService *mp_inst_service; diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 765c6d2a7..669bfe2f5 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -2795,6 +2795,9 @@ PartialService::partial_select (const db::DBox &box, lay::Editable::SelectionMod if (edt::boxes_enabled ()) { shape_flags |= db::ShapeIterator::Boxes; } + if (edt::points_enabled ()) { + shape_flags |= db::ShapeIterator::Points; + } if (edt::texts_enabled ()) { shape_flags |= db::ShapeIterator::Texts; } diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index 51eea026b..d9e374902 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -245,8 +245,12 @@ public: virtual bool implements_mouse_mode (std::string &title) const { - title = m_mouse_mode; - return true; + if (! m_mouse_mode.empty ()) { + title = m_mouse_mode; + return true; + } else { + return false; + } } private: @@ -282,6 +286,11 @@ static tl::RegisteredClass config_decl4 ( "edt::Service(Paths)" ); static tl::RegisteredClass config_decl5 ( + new edt::PluginDeclaration (tl::to_string (tr ("Points")), std::string (), 0, &get_shape_editor_options_pages), + 4014, + "edt::Service(Points)" +); +static tl::RegisteredClass config_decl6 ( new edt::PluginDeclaration (tl::to_string (tr ("Instances")), "instance:edit_mode\t" + tl::to_string (tr ("Instance")) + "\t<:instance_24px.png>" + tl::to_string (tr ("{Create a cell instance}")), &get_inst_options, &get_inst_editor_options_pages), 4020, "edt::Service(CellInstances)" @@ -302,6 +311,7 @@ bool is_enabled () bool polygons_enabled () { return is_enabled (); } bool paths_enabled () { return is_enabled (); } bool boxes_enabled () { return is_enabled (); } +bool points_enabled () { return is_enabled (); } bool texts_enabled () { return is_enabled (); } bool instances_enabled () { return is_enabled (); } diff --git a/src/edt/edt/edtPlugin.h b/src/edt/edt/edtPlugin.h index dc9bef133..a1fb66e63 100644 --- a/src/edt/edt/edtPlugin.h +++ b/src/edt/edt/edtPlugin.h @@ -54,6 +54,7 @@ namespace edt // other types ... bool paths_enabled (); bool boxes_enabled (); + bool points_enabled (); bool texts_enabled (); bool instances_enabled (); diff --git a/src/edt/edt/edtPropertiesPageUtils.cc b/src/edt/edt/edtPropertiesPageUtils.cc index 79363efe2..cd96f632a 100644 --- a/src/edt/edt/edtPropertiesPageUtils.cc +++ b/src/edt/edt/edtPropertiesPageUtils.cc @@ -197,6 +197,42 @@ db::Shape BoxDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db: } } +// ------------------------------------------------------------------------- +// PointDimensionsChangeApplicator implementation + +PointDimensionsChangeApplicator::PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point) + : m_point (point), m_org_point (org_point) +{ + // .. nothing yet .. +} + +db::Shape PointDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db::Shape &shape, double /*dbu*/, bool relative) const +{ + db::Point org_point; + shape.point (org_point); + + db::Point new_point; + if (relative) { + new_point = org_point + (m_point - m_org_point); + } else if (m_point != m_org_point) { + new_point = org_point; + if (m_point.x () != m_org_point.x ()) { + new_point.set_x (m_point.x ()); + } + if (m_point.y () != m_org_point.y ()) { + new_point.set_y (m_point.y ()); + } + } + + if (new_point != org_point) { + // shape changed - replace the old by the new one + return shapes.replace (shape, new_point); + } else { + // shape did not change + return shape; + } +} + // ------------------------------------------------------------------------- // PolygonChangeApplicator implementation diff --git a/src/edt/edt/edtPropertiesPageUtils.h b/src/edt/edt/edtPropertiesPageUtils.h index 3c9dcc4f9..fb9550cdb 100644 --- a/src/edt/edt/edtPropertiesPageUtils.h +++ b/src/edt/edt/edtPropertiesPageUtils.h @@ -131,6 +131,22 @@ private: db::Coord m_l, m_b, m_r, m_t; }; +/** + * @brief A point change applicator + */ +class PointDimensionsChangeApplicator + : public ChangeApplicator +{ +public: + PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point); + + bool supports_relative_mode () const { return true; } + db::Shape do_apply (db::Shapes &shapes, const db::Shape &shape, double dbu, bool relative) const; + +private: + db::Point m_point, m_org_point; +}; + /** * @brief A polygon change applicator */ diff --git a/src/edt/edt/edtPropertiesPages.cc b/src/edt/edt/edtPropertiesPages.cc index 74e7f0d2b..fb524c205 100644 --- a/src/edt/edt/edtPropertiesPages.cc +++ b/src/edt/edt/edtPropertiesPages.cc @@ -853,6 +853,124 @@ BoxPropertiesPage::changed () emit edited (); } +// ------------------------------------------------------------------------- +// PointPropertiesPage implementation + +PointPropertiesPage::PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent) + : ShapePropertiesPage (tl::to_string (tr ("Points")), service, manager, parent), + m_dbu (1.0) +{ + setupUi (this); + setup (); + + if (! readonly ()) { + + connect (x_le, SIGNAL (editingFinished ()), this, SLOT (changed ())); + connect (y_le, SIGNAL (editingFinished ()), this, SLOT (changed ())); + + } else { + + x_le->setReadOnly (true); + y_le->setReadOnly (true); + + } + + connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ())); + connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ())); +} + +std::string +PointPropertiesPage::description (size_t entry) const +{ + const db::Shape &sh = shape (entry); + db::CplxTrans dbu_trans (dbu (entry)); + return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Point%s")), (dbu_trans * sh.point ()).to_string ()); +} + +void +PointPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) +{ + m_dbu = dbu; + + layer_lbl->setText (tl::to_qstring (lname)); + + db::Point point; + shape.point (point); + set_point (point); +} + +ChangeApplicator * +PointPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu) +{ + m_dbu = dbu; + + db::Point point = get_point (); + + db::Point org_point; + shape.point (org_point); + + if (point != org_point) { + return new PointDimensionsChangeApplicator (point, org_point); + } else { + return 0; + } +} + +db::Point +PointPropertiesPage::get_point () const +{ + bool has_error = false; + double x = 0.0, y = 0.0; + + try { + tl::from_string_ext (tl::to_string (x_le->text ()), x); + lay::indicate_error (x_le, (tl::Exception *) 0); + } catch (tl::Exception &ex) { + lay::indicate_error (x_le, &ex); + has_error = true; + } + + try { + tl::from_string_ext (tl::to_string (y_le->text ()), y); + lay::indicate_error (y_le, (tl::Exception *) 0); + } catch (tl::Exception &ex) { + lay::indicate_error (y_le, &ex); + has_error = true; + } + + if (has_error) { + throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes"))); + } + + db::VCplxTrans t = db::VCplxTrans (trans ().inverted ()); + bool du = dbu_units (); + + return point_from_dpoint (db::DPoint (x, y), m_dbu, du, t); +} + +void +PointPropertiesPage::set_point (const db::Point &point) +{ + db::CplxTrans t = db::CplxTrans (trans ()); + db::DPoint pt = db::DPoint (t (point)); + + bool du = dbu_units (); + + x_le->setText (tl::to_qstring (coord_to_string (pt.x (), m_dbu, du))); + y_le->setText (tl::to_qstring (coord_to_string (pt.y (), m_dbu, du))); +} + +void +PointPropertiesPage::changed () +{ + try { + set_point (get_point ()); + } catch (...) { + } + + emit edited (); +} + // ------------------------------------------------------------------------- // TextPropertiesPage implementation diff --git a/src/edt/edt/edtPropertiesPages.h b/src/edt/edt/edtPropertiesPages.h index c95ce5432..534f44020 100644 --- a/src/edt/edt/edtPropertiesPages.h +++ b/src/edt/edt/edtPropertiesPages.h @@ -31,6 +31,7 @@ #include "edtService.h" #include "ui_PolygonPropertiesPage.h" #include "ui_BoxPropertiesPage.h" +#include "ui_PointPropertiesPage.h" #include "ui_PathPropertiesPage.h" #include "ui_EditablePathPropertiesPage.h" #include "ui_TextPropertiesPage.h" @@ -152,6 +153,34 @@ private: void set_box (const db::Box &box); }; +class PointPropertiesPage + : public ShapePropertiesPage, + public Ui::PointPropertiesPage +{ +Q_OBJECT + +public: + PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + + virtual std::string description (size_t entry) const; + virtual std::string description () const { return ShapePropertiesPage::description (); } + virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); + virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); + +public slots: + void changed (); + +protected: + virtual QCheckBox *dbu_checkbox () const { return dbu_cb; } + virtual QCheckBox *abs_checkbox () const { return abs_cb; } + +private: + double m_dbu; + + db::Point get_point () const; + void set_point (const db::Point &point); +}; + class TextPropertiesPage : public ShapePropertiesPage, public Ui::TextPropertiesPage diff --git a/src/edt/edt/edtServiceImpl.cc b/src/edt/edt/edtServiceImpl.cc index a219d38bb..642605718 100644 --- a/src/edt/edt/edtServiceImpl.cc +++ b/src/edt/edt/edtServiceImpl.cc @@ -386,6 +386,20 @@ ShapeEditService::deliver_shape (const db::Box &box) } } +void +ShapeEditService::deliver_shape (const db::Point &point) +{ + if (m_combine_mode == CM_Add) { + if (manager ()) { + manager ()->transaction (tl::to_string (tr ("Create point"))); + } + cell ().shapes (layer ()).insert (point); + if (manager ()) { + manager ()->commit (); + } + } +} + // ----------------------------------------------------------------------------- // PolygonService implementation @@ -816,6 +830,103 @@ BoxService::selection_applies (const lay::ObjectInstPath &sel) const return !sel.is_cell_inst () && sel.shape ().is_box (); } +// ----------------------------------------------------------------------------- +// PointService implementation + +PointService::PointService (db::Manager *manager, lay::LayoutViewBase *view) + : ShapeEditService (manager, view, db::ShapeIterator::Points) +{ + // .. nothing yet .. +} + +#if defined(HAVE_QT) +std::vector +PointService::properties_pages (db::Manager *manager, QWidget *parent) +{ + std::vector pages; + pages.push_back (new edt::PointPropertiesPage (this, manager, parent)); + return pages; +} +#endif + +void +PointService::do_begin_edit (const db::DPoint &p) +{ + get_edit_layer (); + + db::DPoint pp = snap2 (p); + m_p = pp; + + set_edit_marker (new lay::Marker (view (), cv_index ())); + update_marker (); +} + +db::Point +PointService::get_point () const +{ + return db::Point (trans () * m_p); +} + +void +PointService::update_marker () +{ + lay::Marker *marker = dynamic_cast (edit_marker ()); + if (marker) { + + db::Point pt = get_point (); + marker->set (db::Box (pt, pt), db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ()); + + view ()->message (std::string ("x: ") + + tl::micron_to_string (m_p.x ()) + + std::string (" y: ") + + tl::micron_to_string (m_p.y ())); + + } +} + +void +PointService::do_mouse_move_inactive (const db::DPoint &p) +{ + lay::PointSnapToObjectResult snap_details = snap2_details (p); + mouse_cursor_from_snap_details (snap_details); +} + +void +PointService::do_mouse_move (const db::DPoint &p) +{ + do_mouse_move_inactive (p); + + set_cursor (lay::Cursor::cross); + m_p = snap2 (p); + update_marker (); +} + +bool +PointService::do_mouse_click (const db::DPoint &p) +{ + do_mouse_move (p); + return true; +} + +void +PointService::do_finish_edit () +{ + deliver_shape (get_point ()); + commit_recent (view ()); +} + +void +PointService::do_cancel_edit () +{ + // .. nothing yet .. +} + +bool +PointService::selection_applies (const lay::ObjectInstPath &sel) const +{ + return !sel.is_cell_inst () && sel.shape ().is_point (); +} + // ----------------------------------------------------------------------------- // TextService implementation diff --git a/src/edt/edt/edtServiceImpl.h b/src/edt/edt/edtServiceImpl.h index ecb9e4200..8fe8399b7 100644 --- a/src/edt/edt/edtServiceImpl.h +++ b/src/edt/edt/edtServiceImpl.h @@ -67,6 +67,7 @@ protected: void deliver_shape (const db::Polygon &poly); void deliver_shape (const db::Path &path); void deliver_shape (const db::Box &box); + void deliver_shape (const db::Point &point); virtual void current_layer_changed () { } private: @@ -140,6 +141,33 @@ private: db::Box get_box () const; }; +/** + * @brief Implementation of edt::Service for point editing + */ +class PointService + : public ShapeEditService +{ +public: + PointService (db::Manager *manager, lay::LayoutViewBase *view); + +#if defined(HAVE_QT) + virtual std::vector properties_pages (db::Manager *manager, QWidget *parent); +#endif + virtual void do_begin_edit (const db::DPoint &p); + virtual void do_mouse_move (const db::DPoint &p); + virtual void do_mouse_move_inactive (const db::DPoint &p); + virtual bool do_mouse_click (const db::DPoint &p); + virtual void do_finish_edit (); + virtual void do_cancel_edit (); + virtual bool selection_applies (const lay::ObjectInstPath &sel) const; + +private: + db::DPoint m_p; + + void update_marker (); + db::Point get_point () const; +}; + /** * @brief Implementation of edt::Service for text editing */ diff --git a/src/edt/edt/edtUtils.cc b/src/edt/edt/edtUtils.cc index 72375fee9..f8259ffef 100644 --- a/src/edt/edt/edtUtils.cc +++ b/src/edt/edt/edtUtils.cc @@ -260,19 +260,19 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index std::map ::const_iterator pnm = pname_map.find (pv->second.to_string ()); if (pnm != pname_map.end ()) { + db::CplxTrans dbu_trans (layout->dbu ()); + if (sh->is_box ()) { - if (sh->box ().width () == 0 && sh->box ().height () == 0) { - parameters_for_pcell [pnm->second] = tl::Variant (sh->box ().lower_left () * layout->dbu ()); - } else { - parameters_for_pcell [pnm->second] = tl::Variant (sh->box () * layout->dbu ()); - } + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->box ()); } else if (sh->is_edge ()) { - parameters_for_pcell [pnm->second] = tl::Variant (sh->edge () * layout->dbu ()); + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->edge ()); + } else if (sh->is_point ()) { + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->point ()); } else if (sh->is_polygon ()) { // Hint: we don't compress since we don't want to loose information - parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (db::CplxTrans (layout->dbu ()), false)); + parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (dbu_trans, false)); } else if (sh->is_path ()) { - parameters_for_pcell [pnm->second] = tl::Variant (db::CplxTrans (layout->dbu ()) * sh->path ()); + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->path ()); } } @@ -315,7 +315,7 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index } else if (org_parameters[i].is_user ()) { db::DPoint p = org_parameters[i].to_user (); - guiding_shapes.insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props))); + guiding_shapes.insert (db::PointWithProperties(db::Point (p * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props))); } else if (org_parameters[i].is_user ()) { diff --git a/src/laybasic/laybasic/layBitmapRenderer.cc b/src/laybasic/laybasic/layBitmapRenderer.cc index c218cc6bc..e5d67ccb6 100644 --- a/src/laybasic/laybasic/layBitmapRenderer.cc +++ b/src/laybasic/laybasic/layBitmapRenderer.cc @@ -427,7 +427,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans, db::Box bbox = shape.bbox (); double threshold = 1.0 / trans.mag (); - if (bbox.width () <= threshold && bbox.height () <= threshold) { + if (bbox.width () <= threshold && bbox.height () <= threshold && !shape.is_point ()) { db::DPoint dc = trans * bbox.center (); if (fill && ! shape.is_edge ()) { @@ -440,7 +440,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans, render_dot (dc.x (), dc.y (), vertices); } - } else if (shape.is_box ()) { + } else if (shape.is_box () || shape.is_point ()) { draw (bbox, trans, fill, frame, vertices, text); diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.cc b/src/laybasic/laybasic/layRedrawThreadWorker.cc index 6cf2c9e4f..8e868a5bc 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.cc +++ b/src/laybasic/laybasic/layRedrawThreadWorker.cc @@ -1059,7 +1059,7 @@ RedrawThreadWorker::any_shapes (db::cell_index_type cell_index, unsigned int lev int ret = false; const db::Cell &cell = mp_layout->cell (cell_index); - if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel).at_end ()) { + if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel).at_end ()) { ret = true; } else if (levels > 1) { for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); !cc.at_end () && !ret; ++cc) { @@ -1624,7 +1624,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_ size_t current_quad_id = 0; size_t current_array_quad_id = 0; - db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths, mp_prop_sel, m_inv_prop_sel)); + db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel)); while (! shape.at_end ()) { test_snapshot (update_snapshot); diff --git a/src/laybasic/laybasic/layRenderer.cc b/src/laybasic/laybasic/layRenderer.cc index aecdc4a37..8ad78895d 100644 --- a/src/laybasic/laybasic/layRenderer.cc +++ b/src/laybasic/laybasic/layRenderer.cc @@ -65,6 +65,8 @@ Renderer::draw_propstring (const db::Shape &shape, const db::PropertiesRepositor dp = trans * (db::Point () + shape.text_trans ().disp ()); } else if (shape.is_box ()) { dp = trans (shape.box ().p1 ()); + } else if (shape.is_point ()) { + dp = trans (shape.point ()); } else if (shape.is_polygon ()) { db::Shape::polygon_edge_iterator e = shape.begin_edge (); dp = trans ((*e).p1 ()); From e53d432117c66090a844bfc7e5955aa854f3873d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jul 2023 01:01:50 +0200 Subject: [PATCH 2/2] Better support for point-like handles PCells have been featuring point-like handles but they suffered some issues because they have been mapped to degenerated boxes: - hardly visible - could be destroyed using partial editing Now, the database offers points, hence it is possible to store points explicitly, so no tricks need to be played to make them visible. Editing has been implemented to some extent, so it is possible for example to configure handles in the properties dialogs. --- src/edt/edt/edtPartialService.cc | 42 +++++++++++++++++++++++++++++- src/edt/edt/edtService.cc | 25 ++++++++++++++++-- src/laybasic/laybasic/layFinder.cc | 2 +- src/laybasic/laybasic/laySnap.cc | 8 +++++- 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 669bfe2f5..0d9fd63b7 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -849,6 +849,14 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co } + } else if (shape->is_point ()) { + + db::Point tp (shape->point ()); + + if (hit_box.contains (tp)) { + edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0)); + } + } else if (shape->is_text ()) { db::Point tp (shape->text_trans () * db::Point ()); @@ -1000,6 +1008,17 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co } + } else if (shape->is_point ()) { + + db::Point tp (shape->point ()); + + if (hit_box.contains (tp)) { + d = tp.distance (hit_box.center ()); + edge_sel.clear (); + edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0)); + match = true; + } + } else if (shape->is_text ()) { db::Point tp (shape->text_trans () * db::Point ()); @@ -1258,6 +1277,11 @@ PartialService::timeout () db::Point tp (r->first.shape ().text_trans () * db::Point ()); enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true); + } else if (r->first.shape ().is_point ()) { + + db::Point tp (r->first.shape ().point ()); + enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true); + } } @@ -1479,6 +1503,17 @@ PartialService::transform_selection (const db::DTrans &move_trans) shape = shapes.replace (shape, t); } + } else if (shape.is_point ()) { + + db::Point p; + shape.point (p); + + std::map ::const_iterator np = new_points.find (PointWithIndex (p, 0, 0)); + + if (np != new_points.end ()) { + shape = shapes.replace (shape, np->second); + } + } // transform the selection @@ -2204,7 +2239,7 @@ PartialService::del () shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector ())).first->second.push_back (r); } - } else if (shape.is_text ()) { + } else if (shape.is_text () || shape.is_point ()) { shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector ())).first->second.push_back (r); @@ -2684,6 +2719,11 @@ PartialService::do_selection_to_view () db::Point tp (r->first.shape ().text_trans () * db::Point ()); enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false); + } else if (r->first.shape ().is_point ()) { + + db::Point tp (r->first.shape ().point ()); + enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false); + } } diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index aefcf86dd..8afdf95e3 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -1108,7 +1108,20 @@ Service::transient_select (const db::DPoint &pos) lay::ShapeMarker *marker = new lay::ShapeMarker (view (), r->cv_index ()); marker->set (r->shape (), gt, mp_view->cv_transform_variants (r->cv_index (), r->layer ())); - marker->set_vertex_size (0); + + bool is_point = false; + if (r->shape ().is_edge () || r->shape ().is_box ()) { + is_point = r->shape ().bbox ().is_point (); + } else if (r->shape ().is_point ()) { + is_point = true; + } + + if (is_point) { + marker->set_vertex_shape (lay::ViewOp::Cross); + marker->set_vertex_size (9 /*cross vertex size*/); + } else { + marker->set_vertex_size (0); + } marker->set_line_width (1); marker->set_halo (0); @@ -1602,7 +1615,15 @@ Service::do_selection_to_view () } marker->set (r->shape (), gt, *tv_list); - if (r->shape ().is_text ()) { + + bool is_point = false; + if (r->shape ().is_text () || r->shape ().is_point ()) { + is_point = true; + } else if (r->shape ().is_edge () || r->shape ().is_box ()) { + is_point = r->shape ().bbox ().is_point (); + } + + if (is_point) { // show the origins as crosses for texts marker->set_vertex_shape (lay::ViewOp::Cross); marker->set_vertex_size (9 /*cross vertex size*/); diff --git a/src/laybasic/laybasic/layFinder.cc b/src/laybasic/laybasic/layFinder.cc index df2cdcc36..d227d7ae6 100644 --- a/src/laybasic/laybasic/layFinder.cc +++ b/src/laybasic/laybasic/layFinder.cc @@ -606,7 +606,7 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db: match = true; } - } else if (shape->is_box () || shape->is_text ()) { + } else if (shape->is_box () || shape->is_point () || shape->is_text ()) { db::Box box = shape->bbox (); if (text_info () && shape->is_text ()) { diff --git a/src/laybasic/laybasic/laySnap.cc b/src/laybasic/laybasic/laySnap.cc index 4606eb868..b6d268b32 100644 --- a/src/laybasic/laybasic/laySnap.cc +++ b/src/laybasic/laybasic/laySnap.cc @@ -598,7 +598,7 @@ private: const db::Shapes &shapes = cell.shapes (l); - db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel); + db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel); while (! shape.at_end () && m_tests > 0) { --m_tests; @@ -653,6 +653,12 @@ private: test_edge (t * db::Edge (box.p2 (), db::Point (box.right (), box.bottom ()))); test_edge (t * db::Edge (db::Point (box.right (), box.bottom ()), box.p1 ())); + } else if (shape->is_point ()) { + + const db::Point &p = shape->point (); + + test_edge (t * db::Edge (p, p)); + } ++shape;