mirror of https://github.com/KLayout/klayout.git
Fixing a small glitch: drawing into a ghost cell is possible, but did not turn off the ghost cell flag. Now the flag is still on, but a non-empty cell is not considered a ghost cell for most purposes.
This commit is contained in:
parent
95d6b0aca5
commit
bc49082955
|
|
@ -945,7 +945,7 @@ std::string
|
|||
Cell::get_display_name () const
|
||||
{
|
||||
tl_assert (layout () != 0);
|
||||
if (is_ghost_cell () && empty ()) {
|
||||
if (is_real_ghost_cell ()) {
|
||||
return std::string ("(") + layout ()->cell_name (cell_index ()) + std::string (")");
|
||||
} else {
|
||||
return layout ()->cell_name (cell_index ());
|
||||
|
|
@ -959,6 +959,20 @@ Cell::set_name (const std::string &name)
|
|||
layout ()->rename_cell (cell_index (), name.c_str ());
|
||||
}
|
||||
|
||||
void
|
||||
Cell::set_ghost_cell (bool g)
|
||||
{
|
||||
// NOTE: this change is not undo managed
|
||||
if (m_ghost_cell != g) {
|
||||
|
||||
m_ghost_cell = g;
|
||||
tl_assert (layout () != 0);
|
||||
// To trigger a redraw and cell tree rebuild
|
||||
layout ()->cell_name_changed ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cell::check_locked () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -925,15 +925,26 @@ public:
|
|||
return m_ghost_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the cell is a "real" ghost cell
|
||||
*
|
||||
* A ghost cell is a real ghost cell only if the ghost cell flag is set
|
||||
* and the cell is empty. Only in that case for example the cell is written
|
||||
* to GDS files as a ghost cell.
|
||||
*
|
||||
* Otherwise, the ghost cell flag is mostly ignored.
|
||||
*/
|
||||
bool is_real_ghost_cell () const
|
||||
{
|
||||
return m_ghost_cell && empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the "ghost cell" flag
|
||||
*
|
||||
* See "is_ghost_cell" for a description of this property.
|
||||
*/
|
||||
void set_ghost_cell (bool g)
|
||||
{
|
||||
m_ghost_cell = g;
|
||||
}
|
||||
void set_ghost_cell (bool g);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the cell is locked
|
||||
|
|
|
|||
|
|
@ -1417,7 +1417,7 @@ Layout::add_cell (const char *name)
|
|||
if (cm != m_cell_map.end ()) {
|
||||
|
||||
const db::Cell &c= cell (cm->second);
|
||||
if (c.is_ghost_cell () && c.empty ()) {
|
||||
if (c.is_real_ghost_cell ()) {
|
||||
// ghost cells are available as new cells - the idea is to
|
||||
// treat them as non-existing.
|
||||
return cm->second;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,14 @@ public:
|
|||
return m_busy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue a "cell name changed event"
|
||||
*/
|
||||
void cell_name_changed ()
|
||||
{
|
||||
cell_name_changed_event ();
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class PropertiesRepository;
|
||||
|
||||
|
|
@ -191,14 +199,6 @@ protected:
|
|||
*/
|
||||
virtual void do_update () { }
|
||||
|
||||
/**
|
||||
* @brief Issue a "prop id's changed event"
|
||||
*/
|
||||
void cell_name_changed ()
|
||||
{
|
||||
cell_name_changed_event ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue a "layer properties changed event"
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3450,6 +3450,9 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"To satisfy the references inside the layout, a dummy cell is created in this case\n"
|
||||
"which has the \"ghost cell\" flag set to true.\n"
|
||||
"\n"
|
||||
"A ghost cell is a real ghost cell only if the cell is empty. In that case, it is written "
|
||||
"as a ghost cell to GDS files for example. If a cell is not empty, this flag is ignored.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.20.\n"
|
||||
) +
|
||||
gsi::method ("ghost_cell=", &db::Cell::set_ghost_cell, gsi::arg ("flag"),
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ Finder::do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, cons
|
|||
&& (t * m_cell_box_convert (cell)).touches (m_scan_region)
|
||||
&& (mp_view->select_inside_pcells_mode () || !cell.is_proxy ())
|
||||
&& !mp_view->is_cell_hidden (cell.cell_index (), m_cv_index)
|
||||
&& !cell.is_ghost_cell ()) {
|
||||
&& !cell.is_real_ghost_cell ()) {
|
||||
|
||||
db::ICplxTrans it = t.inverted ();
|
||||
db::Box scan_box (it * m_scan_region);
|
||||
|
|
@ -846,7 +846,7 @@ InstFinder::reset_counter ()
|
|||
bool
|
||||
InstFinder::consider_cell (const db::Cell &cell) const
|
||||
{
|
||||
return cell.is_ghost_cell () ? m_consider_ghost_cells : m_consider_normal_cells;
|
||||
return cell.is_real_ghost_cell () ? m_consider_ghost_cells : m_consider_normal_cells;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -877,7 +877,7 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
// just consider the instances exactly at the last level of
|
||||
// hierarchy (this is where the boxes are drawn) or of cells that
|
||||
// are hidden.
|
||||
if (level == max_level () - 1 || inst_cell.is_proxy () || inst_cell.is_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
if (level == max_level () - 1 || inst_cell.is_proxy () || inst_cell.is_real_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
|
||||
db::box_convert <db::CellInst, false> bc (layout ());
|
||||
for (db::CellInstArray::iterator p = cell_inst.begin_touching (search_box, bc); ! p.at_end (); ++p) {
|
||||
|
|
@ -885,7 +885,7 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
checkpoint ();
|
||||
|
||||
db::Box ibox;
|
||||
if (! m_visible_layers || level == mp_view->get_max_hier_levels () - 1 || inst_cell.is_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
if (! m_visible_layers || level == mp_view->get_max_hier_levels () - 1 || inst_cell.is_real_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
ibox = inst_cell.bbox_with_empty ();
|
||||
} else if (inst_cell.bbox ().empty ()) {
|
||||
// empty cells cannot be found by visible layers, so we always select them here
|
||||
|
|
@ -954,7 +954,7 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
// just consider the instances exactly at the last level of
|
||||
// hierarchy (this is where the boxes are drawn) or if of cells that
|
||||
// are hidden.
|
||||
if (level == max_level () - 1 || inst_cell.is_proxy () || inst_cell.is_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
if (level == max_level () - 1 || inst_cell.is_proxy () || inst_cell.is_real_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
|
||||
db::box_convert <db::CellInst, false> bc (layout ());
|
||||
for (db::CellInstArray::iterator p = cell_inst.begin_touching (search_box, bc); ! p.at_end (); ++p) {
|
||||
|
|
@ -965,7 +965,7 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
double d = std::numeric_limits<double>::max ();
|
||||
|
||||
db::Box ibox;
|
||||
if (! m_visible_layers || level == mp_view->get_max_hier_levels () - 1 || inst_cell.is_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
if (! m_visible_layers || level == mp_view->get_max_hier_levels () - 1 || inst_cell.is_real_ghost_cell () || mp_view->is_cell_hidden (inst_cell.cell_index (), m_cv_index)) {
|
||||
ibox = inst_cell.bbox_with_empty ();
|
||||
} else if (inst_cell.bbox ().empty ()) {
|
||||
// empty cells cannot be found by visible layers, so we always select them here
|
||||
|
|
|
|||
|
|
@ -714,7 +714,7 @@ RedrawThreadWorker::setup (LayoutViewBase *view, RedrawThreadCanvas *canvas, con
|
|||
std::set <lay::LayoutViewBase::cell_index_type> &gc = m_ghost_cells [i];
|
||||
const db::Layout &ly = view->cellview (i)->layout ();
|
||||
for (auto c = ly.begin (); c != ly.end (); ++c) {
|
||||
if (c->is_ghost_cell ()) {
|
||||
if (c->is_real_ghost_cell ()) {
|
||||
gc.insert (c->cell_index ());
|
||||
}
|
||||
}
|
||||
|
|
@ -950,12 +950,12 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
|
|||
bbox_for_label = bbox;
|
||||
}
|
||||
|
||||
if (for_ghosts && cell.is_ghost_cell ()) {
|
||||
if (for_ghosts && cell.is_real_ghost_cell ()) {
|
||||
|
||||
// paint the box on this level
|
||||
draw_cell (drawing_context, level, trans, bbox, bbox_for_label, empty_cell, mp_layout->display_name (ci), opt_bitmap);
|
||||
|
||||
} else if (! for_ghosts && ! cell.is_ghost_cell () && (level == m_to_level || (m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()))) {
|
||||
} else if (! for_ghosts && ! cell.is_real_ghost_cell () && (level == m_to_level || (m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()))) {
|
||||
|
||||
// paint the box on this level
|
||||
draw_cell (drawing_context, level, trans, bbox, bbox_for_label, empty_cell, mp_layout->display_name (ci), opt_bitmap);
|
||||
|
|
@ -1186,12 +1186,12 @@ RedrawThreadWorker::draw_box_properties_impl (bool drawing_context, db::cell_ind
|
|||
|
||||
// small cell dropped
|
||||
|
||||
} else if (for_ghosts && cell.is_ghost_cell ()) {
|
||||
} else if (for_ghosts && cell.is_real_ghost_cell ()) {
|
||||
|
||||
// paint the box on this level
|
||||
draw_cell_properties (drawing_context, level, trans, bbox, prop_id);
|
||||
|
||||
} else if (! for_ghosts && ! cell.is_ghost_cell () && (level == m_to_level || (m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()))) {
|
||||
} else if (! for_ghosts && ! cell.is_real_ghost_cell () && (level == m_to_level || (m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()))) {
|
||||
|
||||
// paint the box on this level
|
||||
draw_cell_properties (drawing_context, level, trans, bbox, prop_id);
|
||||
|
|
@ -1317,7 +1317,7 @@ RedrawThreadWorker::any_shapes (db::cell_index_type cell_index, unsigned int lev
|
|||
|
||||
// Ghost cells are not drawn either
|
||||
const db::Cell &cell = mp_layout->cell (cell_index);
|
||||
if (cell.is_ghost_cell ()) {
|
||||
if (cell.is_real_ghost_cell ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1359,7 +1359,7 @@ RedrawThreadWorker::any_cell_box (db::cell_index_type cell_index, unsigned int l
|
|||
|
||||
// ghost cells are also drawn
|
||||
const db::Cell &cell = mp_layout->cell (cell_index);
|
||||
if (cell.is_ghost_cell ()) {
|
||||
if (cell.is_real_ghost_cell ()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1400,7 +1400,7 @@ RedrawThreadWorker::any_text_shapes (db::cell_index_type cell_index, unsigned in
|
|||
|
||||
// Ghost cells are not drawn either
|
||||
const db::Cell &cell = mp_layout->cell (cell_index);
|
||||
if (cell.is_ghost_cell ()) {
|
||||
if (cell.is_real_ghost_cell ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1503,7 +1503,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
|
|||
|
||||
} else if (! bbox.empty ()) {
|
||||
|
||||
bool hidden = cell.is_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
bool hidden = cell.is_real_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
bool need_to_dive = (level + 1 < m_to_level) && ! hidden;
|
||||
|
||||
db::Box cell_bbox = cell.bbox ();
|
||||
|
|
@ -1637,7 +1637,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
|
|||
++inst;
|
||||
|
||||
db::cell_index_type new_ci = cell_inst.object ().cell_index ();
|
||||
bool hidden = mp_layout->cell (new_ci).is_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (new_ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
bool hidden = mp_layout->cell (new_ci).is_real_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (new_ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
|
||||
db::Box cell_box = mp_layout->cell (new_ci).bbox (m_layer);
|
||||
if (! cell_box.empty () && ! hidden) {
|
||||
|
|
@ -1939,7 +1939,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_
|
|||
++inst;
|
||||
|
||||
db::cell_index_type new_ci = cell_inst.object ().cell_index ();
|
||||
bool hidden = mp_layout->cell (new_ci).is_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (new_ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
bool hidden = mp_layout->cell (new_ci).is_real_ghost_cell () || ((m_cv_index < int (m_hidden_cells.size ()) && m_hidden_cells [m_cv_index].find (new_ci) != m_hidden_cells [m_cv_index].end ()));
|
||||
|
||||
db::Box new_cell_box = mp_layout->cell (new_ci).bbox (m_layer);
|
||||
if (! new_cell_box.empty () && ! hidden) {
|
||||
|
|
@ -2096,7 +2096,7 @@ RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_typ
|
|||
db::Box cell_bbox = cell.bbox ();
|
||||
|
||||
// Nothing to draw
|
||||
if (bbox.empty () || cell.is_ghost_cell ()) {
|
||||
if (bbox.empty () || cell.is_real_ghost_cell ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -577,7 +577,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
|
|||
|
||||
// don't write ghost cells unless they are not empty (any more)
|
||||
// also don't write proxy cells which are not employed
|
||||
if ((! cref.is_ghost_cell () || ! cref.empty ()) && (! cref.is_proxy () || ! cref.is_top ())) {
|
||||
if (! cref.is_real_ghost_cell () && (! cref.is_proxy () || ! cref.is_top ())) {
|
||||
|
||||
try {
|
||||
write_cell (layout, cref, layers, cell_set, sf, time_data);
|
||||
|
|
|
|||
|
|
@ -913,7 +913,7 @@ Writer::make_meta_data (const db::Cell *cell, stream::metaData::MetaData::Builde
|
|||
void
|
||||
Writer::write_cell (db::cell_index_type ci, kj::BufferedOutputStream &os)
|
||||
{
|
||||
bool needs_layout_view = ! mp_layout->cell (ci).is_ghost_cell ();
|
||||
bool needs_layout_view = ! mp_layout->cell (ci).is_real_ghost_cell ();
|
||||
bool needs_meta_data_view = mp_layout->begin_meta (ci) != mp_layout->end_meta (ci);
|
||||
|
||||
capnp::MallocMessageBuilder message;
|
||||
|
|
|
|||
|
|
@ -1443,12 +1443,6 @@ static bool must_write_cell (const db::Cell &cref)
|
|||
return ! cref.is_proxy () || ! cref.is_top ();
|
||||
}
|
||||
|
||||
static bool skip_cell_body (const db::Cell &cref)
|
||||
{
|
||||
// Skip cell bodies for ghost cells unless empty (they are not longer ghost cells in this case)
|
||||
return cref.is_ghost_cell () && cref.empty ();
|
||||
}
|
||||
|
||||
void
|
||||
OASISWriter::create_cell_nstrings (const db::Layout &layout, const std::set <db::cell_index_type> &cell_set)
|
||||
{
|
||||
|
|
@ -1670,7 +1664,7 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save
|
|||
mp_cell = &cref;
|
||||
|
||||
// skip cell body if the cell is not to be written
|
||||
if (skip_cell_body (cref)) {
|
||||
if (cref.is_real_ghost_cell ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue