Introducing fallback transformation variants for empty layer lists. This allows editing layouts without any layers and only instances.

This commit is contained in:
Matthias Koefferlein 2025-08-10 21:29:53 +02:00
parent 7667932a00
commit fdb28800f7
5 changed files with 93 additions and 35 deletions

View File

@ -1115,7 +1115,7 @@ Service::click_proximity (const db::DPoint &pos, lay::Editable::SelectionMode mo
lay::InstFinder finder (true, view ()->is_editable () && m_top_level_sel, view ()->is_editable () /*full arrays in editable mode*/, true /*enclose_inst*/, exclude, true /*visible layers*/);
// go through all cell views
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants ();
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants_with_empty();
for (std::set< std::pair<db::DCplxTrans, int> >::const_iterator v = variants.begin (); v != variants.end (); ++v) {
finder.find (view (), v->second, v->first, search_box);
}
@ -1164,7 +1164,7 @@ Service::transient_select (const db::DPoint &pos)
lay::InstFinder finder (true, view ()->is_editable () && m_top_level_sel, view ()->is_editable () /*full arrays in editable mode*/, true /*enclose instances*/, &m_previous_selection, true /*visible layers only*/);
// go through all transform variants
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants ();
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants_with_empty ();
for (std::set< std::pair<db::DCplxTrans, int> >::const_iterator v = variants.begin (); v != variants.end (); ++v) {
finder.find (view (), v->second, v->first, search_box);
}
@ -1185,7 +1185,7 @@ Service::transient_select (const db::DPoint &pos)
db::Instance inst = r->back ().inst_ptr;
std::vector<db::DCplxTrans> tv = mp_view->cv_transform_variants (r->cv_index ());
std::vector<db::DCplxTrans> tv = mp_view->cv_transform_variants_with_empty (r->cv_index ());
if (view ()->is_editable ()) {
#if 0
@ -1498,7 +1498,7 @@ Service::select (const db::DBox &box, lay::Editable::SelectionMode mode)
lay::InstFinder finder (box.is_point (), view ()->is_editable () && m_top_level_sel, view ()->is_editable () /*full arrays in editable mode*/, true /*enclose_inst*/, exclude, true /*only visible layers*/);
// go through all cell views
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants ();
std::set< std::pair<db::DCplxTrans, int> > variants = view ()->cv_transform_variants_with_empty ();
for (std::set< std::pair<db::DCplxTrans, int> >::const_iterator v = variants.begin (); v != variants.end (); ++v) {
finder.find (view (), v->second, v->first, search_box);
}
@ -1754,6 +1754,10 @@ Service::do_selection_to_view ()
// build the transformation variants cache
TransformationVariants tv (view ());
// prepare a default transformation for empty variants
std::vector<db::DCplxTrans> empty_tv;
empty_tv.push_back (db::DCplxTrans ());
// Build markers
for (EditableSelectionIterator r = begin_selection (); ! r.at_end (); ++r) {
@ -1769,39 +1773,39 @@ Service::do_selection_to_view ()
if (m_cell_inst_service) {
const std::vector<db::DCplxTrans> *tv_list = tv.per_cv (r->cv_index ());
if (tv_list != 0) {
if (tv_list == 0) {
tv_list = &empty_tv;
}
if (view ()->is_editable ()) {
if (view ()->is_editable ()) {
#if 0
// to show the content of the cell when the instance is selected:
lay::InstanceMarker *marker = new lay::InstanceMarker (view (), r->cv_index (), ! show_shapes_of_instances (), show_shapes_of_instances () ? max_shapes_of_instances () : 0);
// to show the content of the cell when the instance is selected:
lay::InstanceMarker *marker = new lay::InstanceMarker (view (), r->cv_index (), ! show_shapes_of_instances (), show_shapes_of_instances () ? max_shapes_of_instances () : 0);
#else
lay::InstanceMarker *marker = new lay::InstanceMarker (view (), r->cv_index ());
lay::InstanceMarker *marker = new lay::InstanceMarker (view (), r->cv_index ());
#endif
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
if (r->seq () > 0 && m_indicate_secondary_selection) {
marker->set_dither_pattern (3);
}
marker->set (r->back ().inst_ptr, gt, *tv_list);
m_markers.push_back (std::make_pair (r.operator-> (), marker));
} else {
lay::Marker *marker = new lay::Marker (view (), r->cv_index ());
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
if (r->seq () > 0 && m_indicate_secondary_selection) {
marker->set_dither_pattern (3);
}
db::box_convert<db::CellInst> bc (cv->layout ());
marker->set (bc (r->back ().inst_ptr.cell_inst ().object ()), gt * r->back ().inst_ptr.cell_inst ().complex_trans (*r->back ().array_inst), *tv_list);
m_markers.push_back (std::make_pair (r.operator-> (), marker));
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
if (r->seq () > 0 && m_indicate_secondary_selection) {
marker->set_dither_pattern (3);
}
marker->set (r->back ().inst_ptr, gt, *tv_list);
m_markers.push_back (std::make_pair (r.operator-> (), marker));
} else {
lay::Marker *marker = new lay::Marker (view (), r->cv_index ());
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
if (r->seq () > 0 && m_indicate_secondary_selection) {
marker->set_dither_pattern (3);
}
db::box_convert<db::CellInst> bc (cv->layout ());
marker->set (bc (r->back ().inst_ptr.cell_inst ().object ()), gt * r->back ().inst_ptr.cell_inst ().complex_trans (*r->back ().array_inst), *tv_list);
m_markers.push_back (std::make_pair (r.operator-> (), marker));
}

View File

@ -735,7 +735,7 @@ InstFinder::find (lay::LayoutViewBase *view, const db::DBox &region_mu)
progress.set_format ("");
mp_progress = &progress;
std::set< std::pair<db::DCplxTrans, int> > variants = view->cv_transform_variants ();
std::set< std::pair<db::DCplxTrans, int> > variants = view->cv_transform_variants_with_empty ();
for (std::set< std::pair<db::DCplxTrans, int> >::const_iterator v = variants.begin (); v != variants.end (); ++v) {
find (view, v->second, v->first, region_mu);
}

View File

@ -3864,8 +3864,13 @@ LayoutViewBase::full_box () const
db::DBox bbox;
for (LayerPropertiesConstIterator l = get_properties ().begin_const_recursive (); ! l.at_end (); ++l) {
bbox += l->overall_bbox ();
auto tv = cv_transform_variants_with_empty ();
for (auto i = tv.begin (); i != tv.end (); ++i) {
const lay::CellView &cv = cellview (i->second);
if (cv.is_valid ()) {
double dbu = cv->layout ().dbu ();
bbox += (i->first * db::CplxTrans (dbu) * cv.context_trans ()) * cv.cell ()->bbox_with_empty ();
}
}
for (lay::AnnotationShapes::iterator a = annotation_shapes ().begin (); ! a.at_end (); ++a) {
@ -5986,6 +5991,16 @@ LayoutViewBase::cv_transform_variants (int cv_index) const
return std::vector<db::DCplxTrans> (trns_variants.begin (), trns_variants.end ());
}
std::vector<db::DCplxTrans>
LayoutViewBase::cv_transform_variants_with_empty (int cv_index) const
{
std::vector<db::DCplxTrans> trns_variants = cv_transform_variants (cv_index);
if (trns_variants.empty ()) {
trns_variants.push_back (db::DCplxTrans ());
}
return trns_variants;
}
std::vector<db::DCplxTrans>
LayoutViewBase::cv_transform_variants (int cv_index, unsigned int layer) const
{
@ -6046,7 +6061,30 @@ LayoutViewBase::cv_transform_variants () const
return box_variants;
}
db::InstElement
std::set< std::pair<db::DCplxTrans, int> >
LayoutViewBase::cv_transform_variants_with_empty () const
{
std::set< std::pair<db::DCplxTrans, int> > box_variants = cv_transform_variants ();
// add a default box variant for the CVs not present in the layer list to
// draw boxes at least.
std::vector<bool> cv_present;
cv_present.resize (m_cellviews.size ());
for (auto bv = box_variants.begin (); bv != box_variants.end (); ++bv) {
if (bv->second >= 0 && bv->second < int (cv_present.size ())) {
cv_present[bv->second] = true;
}
}
for (auto i = cv_present.begin (); i != cv_present.end (); ++i) {
box_variants.insert (std::make_pair (db::DCplxTrans (), int (i - cv_present.begin ())));
}
return box_variants;
}
db::InstElement
LayoutViewBase::ascend (int index)
{
tl_assert (int (m_cellviews.size ()) > index && cellview_iter (index)->is_valid ());

View File

@ -1674,11 +1674,27 @@ public:
*/
std::set< std::pair<db::DCplxTrans, int> > cv_transform_variants () const;
/**
* @brief Get a list of cellview index and transform variants including empty cellviews
*
* This version delivers a unit-transformation variant for cell views for which
* no layer is present. This version is used for instance box drawing.
*/
std::set< std::pair<db::DCplxTrans, int> > cv_transform_variants_with_empty () const;
/**
* @brief Get the global transform variants for a given cellview index
*/
std::vector<db::DCplxTrans> cv_transform_variants (int cv_index) const;
/**
* @brief Get the global transform variants for a given cellview index including empty cellviews
*
* This version delivers a unit-transformation variant for cell views for which
* no layer is present. This version is used for instance box drawing.
*/
std::vector<db::DCplxTrans> cv_transform_variants_with_empty (int cv_index) const;
/**
* @brief Get the global transform variants for a given cellview index and layer
*/

View File

@ -575,7 +575,7 @@ RedrawThreadWorker::setup (LayoutViewBase *view, RedrawThreadCanvas *canvas, con
m_nlayers = mp_redraw_thread->num_layers ();
m_box_variants = view->cv_transform_variants ();
m_box_variants = view->cv_transform_variants_with_empty ();
}
void