Issue #2219 (drawing of empty cells)

1. Optimiziation - not more than one empty cell per pixel
   This is not very efficient on the available test cases.
2. Introducing a virtual dimension for the empty cells
   for the purpose of label scaling.
   With this, the labels are scaled (if a scalable font
   is selected) and not drawn when becoming very small.
   The parameter is found in the setup pages under
   Display/Cells.
This commit is contained in:
Matthias Koefferlein 2025-11-20 22:55:40 +01:00
parent dacb3230d5
commit 12b74517a6
8 changed files with 348 additions and 196 deletions

View File

@ -342,6 +342,7 @@ LayoutViewBase::init (db::Manager *mgr)
m_box_text_transform = true;
m_box_font = 0;
m_min_size_for_label = 16;
m_empty_cell_dimension = 4.0;
m_cell_box_visible = true;
m_ghost_cells_visible = true;
m_text_visible = true;
@ -944,6 +945,13 @@ LayoutViewBase::configure (const std::string &name, const std::string &value)
min_inst_label_size (n);
return true;
} else if (name == cfg_empty_cell_dimension) {
double n;
tl::from_string (value, n);
empty_cell_dimension (n);
return true;
} else if (name == cfg_cell_box_text_font) {
int n;
@ -5403,7 +5411,16 @@ LayoutViewBase::min_inst_label_size (int px)
}
}
void
void
LayoutViewBase::empty_cell_dimension (double um)
{
if (m_empty_cell_dimension != um) {
m_empty_cell_dimension = um;
redraw ();
}
}
void
LayoutViewBase::text_visible (bool vis)
{
if (m_text_visible != vis) {

View File

@ -1149,7 +1149,20 @@ public:
return m_min_size_for_label;
}
/**
/**
* @brief Empty cell dimension for the purpose of label generation setter
*/
void empty_cell_dimension (double um);
/**
* @brief Empty cell dimension for the purpose of label generation getter
*/
int empty_cell_dimension () const
{
return m_empty_cell_dimension;
}
/**
* @brief Visibility of text objects
*/
void text_visible (bool vis);
@ -2941,6 +2954,7 @@ private:
bool m_box_text_transform;
unsigned int m_box_font;
int m_min_size_for_label;
double m_empty_cell_dimension;
bool m_cell_box_visible;
bool m_ghost_cells_visible;

View File

@ -55,6 +55,7 @@ public:
options.push_back (std::pair<std::string, std::string> (cfg_current_lib_view, ""));
options.push_back (std::pair<std::string, std::string> (cfg_hide_empty_layers, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_min_inst_label_size, "16"));
options.push_back (std::pair<std::string, std::string> (cfg_empty_cell_dimension, "4"));
options.push_back (std::pair<std::string, std::string> (cfg_cell_box_text_font, "0"));
options.push_back (std::pair<std::string, std::string> (cfg_cell_box_text_transform, "true"));
options.push_back (std::pair<std::string, std::string> (cfg_cell_box_color, "auto"));

View File

@ -40,6 +40,90 @@ static inline db::Box safe_transformed_box (const db::Box &box, const db::ICplxT
return db::Box (db);
}
static bool
has_zero_bit (const lay::Bitmap *bitmap, unsigned int ixmin, unsigned int iymin, unsigned int ixmax, unsigned int iymax)
{
uint32_t imin = ixmin / 32;
uint32_t imax = ixmax / 32;
if (imin == imax) {
uint32_t m = ((unsigned int) 0xffffffff << (ixmin % 32)) & ((unsigned int) 0xffffffff >> (31 - (ixmax % 32)));
for (unsigned int y = iymin; y <= iymax; ++y) {
if (bitmap->is_scanline_empty (y)) {
return true;
}
if ((bitmap->scanline (y) [imin] & m) != m) {
return true;
}
}
} else {
uint32_t m1 = ((unsigned int) 0xffffffff << (ixmin % 32));
uint32_t m2 = ((unsigned int) 0xffffffff >> (31 - (ixmax % 32)));
for (unsigned int y = iymin; y <= iymax; ++y) {
if (bitmap->is_scanline_empty (y)) {
return true;
}
if ((bitmap->scanline (y) [imin] & m1) != m1) {
return true;
}
for (unsigned int i = imin + 1; i < imax; ++i) {
if (bitmap->scanline (y) [i] != 0xffffffff) {
return true;
}
}
if ((bitmap->scanline (y) [imax] & m2) != m2) {
return true;
}
}
}
return false;
}
static bool
skip_quad (const db::Box &qb, const lay::Bitmap *vertex_bitmap, const db::CplxTrans &trans)
{
double threshold = 32 / trans.mag (); // only check cells below 32x32 pixels
if (qb.empty () || qb.width () > threshold || qb.height () > threshold || !vertex_bitmap) {
return false;
}
db::DBox qb_trans = (trans * qb) & db::DBox (0, 0, vertex_bitmap->width () - 1.0 - 1e-6, vertex_bitmap->height () - 1.0 - 1e-6);
if (qb_trans.empty ()) {
return true;
}
int ixmin = (unsigned int)(qb_trans.left () + 0.5);
int ixmax = (unsigned int)(qb_trans.right () + 0.5);
int iymin = (unsigned int)(qb_trans.bottom () + 0.5);
int iymax = (unsigned int)(qb_trans.top () + 0.5);
if (! has_zero_bit (vertex_bitmap, ixmin, iymin, ixmax, iymax)) {
return true; // skip
} else {
return false;
}
}
inline void
copy_bitmap (const lay::Bitmap *from, lay::Bitmap *to, int dx, int dy)
{
if (to) {
to->merge (from, dx, dy);
}
}
// -------------------------------------------------------------
// RedrawThreadWorker implementation
@ -61,6 +145,7 @@ RedrawThreadWorker::RedrawThreadWorker (RedrawThread *redraw_thread)
m_box_text_transform = false;
m_box_font = 0;
m_min_size_for_label = 1;
m_empty_cell_dimension = 1.0;
m_text_font = 0;
m_text_visible = false;
m_text_lazy_rendering = false;
@ -600,6 +685,7 @@ RedrawThreadWorker::setup (LayoutViewBase *view, RedrawThreadCanvas *canvas, con
m_from_level_default = view->get_hier_levels ().first;
m_to_level_default = view->get_hier_levels ().second;
m_min_size_for_label = view->min_inst_label_size ();
m_empty_cell_dimension = view->empty_cell_dimension ();
m_box_text_transform = view->cell_box_text_transform ();
m_box_font = view->cell_box_text_font ();
m_text_font = view->text_font ();
@ -680,7 +766,7 @@ RedrawThreadWorker::test_snapshot (const UpdateSnapshotCallback *update_snapshot
}
void
RedrawThreadWorker::draw_cell (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, bool empty_cell, const std::string &txt)
RedrawThreadWorker::draw_cell (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, const db::Box &box_for_label, bool empty_cell, const std::string &txt, lay::Bitmap *opt_bitmap)
{
lay::Renderer &r = *mp_renderer;
@ -699,13 +785,17 @@ RedrawThreadWorker::draw_cell (bool drawing_context, int level, const db::CplxTr
if (empty_cell) {
r.draw (dbox, 0, contour, vertices, 0);
if (opt_bitmap) {
r.draw (dbox, 0, 0, opt_bitmap, 0);
}
} else {
r.draw (dbox, fill, contour, 0, 0);
}
if (! txt.empty () && (empty_cell || (dbox.width () > m_min_size_for_label && dbox.height () > m_min_size_for_label))) {
db::DBox dbox_for_label = trans * box_for_label;
if (! txt.empty () && (empty_cell || (dbox_for_label.width () > m_min_size_for_label && dbox_for_label.height () > m_min_size_for_label))) {
// Hint: we render to contour because the texts plane is reserved for properties
r.draw (dbox, txt,
r.draw (dbox_for_label, txt,
db::Font (m_box_font),
db::HAlignCenter,
db::VAlignCenter,
@ -817,34 +907,58 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
return;
}
std::unique_ptr<lay::Bitmap> opt_bitmap;
unsigned int plane_group = 2;
if (drawing_context) {
plane_group = 0;
} else if (m_child_context_enabled && level + 1 > 0) {
plane_group = 1;
}
lay::CanvasPlane *vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
lay::Bitmap *vertex_bitmap = dynamic_cast<lay::Bitmap *> (vertex);
if (vertex_bitmap) {
opt_bitmap.reset (new lay::Bitmap (vertex_bitmap->width (), vertex_bitmap->height (), vertex_bitmap->resolution (), vertex_bitmap->font_resolution ()));
}
for (std::vector<db::Box>::const_iterator b = redraw_regions.begin (); b != redraw_regions.end (); ++b) {
draw_boxes_impl (drawing_context, ci, trans, *b, level, for_ghosts);
draw_boxes_impl (drawing_context, ci, trans, *b, level, for_ghosts, opt_bitmap.get ());
}
}
void
RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, bool for_ghosts)
RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, bool for_ghosts, lay::Bitmap *opt_bitmap)
{
lay::Renderer &r = *mp_renderer;
const db::Cell &cell = mp_layout->cell (ci);
// small cells are dropped
if (m_drop_small_cells && drop_cell (cell, trans)) {
return;
}
// For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox_with_empty ();
bool empty_cell = cell.bbox ().empty ();
if (m_drop_small_cells && drop_cell (cell, trans)) {
db::Box bbox_for_label;
if (empty_cell) {
db::Coord d = db::coord_traits<db::Coord>::rounded (0.5 * m_empty_cell_dimension / mp_layout->dbu ());
bbox_for_label = bbox.enlarged (db::Vector (d, d));
} else {
bbox_for_label = bbox;
}
// small cell dropped
} else if (for_ghosts && cell.is_ghost_cell ()) {
if (for_ghosts && cell.is_ghost_cell ()) {
// paint the box on this level
draw_cell (drawing_context, level, trans, bbox, empty_cell, mp_layout->display_name (ci));
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 ()))) {
// paint the box on this level
draw_cell (drawing_context, level, trans, bbox, empty_cell, mp_layout->display_name (ci));
draw_cell (drawing_context, level, trans, bbox, bbox_for_label, empty_cell, mp_layout->display_name (ci), opt_bitmap);
} else if (level < m_to_level) {
@ -855,7 +969,7 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
// the cell is a very small box and we know there must be
// some level at which to draw the boundary: just draw it
// here and stop looking further down ..
draw_cell (drawing_context, level, trans, bbox, empty_cell, std::string ());
draw_cell (drawing_context, level, trans, bbox, bbox_for_label, empty_cell, std::string (), opt_bitmap);
}
} else {
@ -884,6 +998,8 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
bool anything = false;
db::cell_index_type last_ci = std::numeric_limits<db::cell_index_type>::max ();
size_t current_quad_id = 0;
db::Cell::touching_iterator inst = cell.begin_touching (*v);
while (! inst.at_end ()) {
@ -893,6 +1009,20 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
db::Box new_cell_box = cell_inst.bbox (bc);
bool empty_inst_cell = mp_layout->cell (new_ci).bbox ().empty ();
// skip this quad if we have drawn something here already
size_t qid = inst.quad_id ();
bool skip = false;
if (empty_inst_cell && qid != current_quad_id) {
current_quad_id = qid;
skip = opt_bitmap && skip_quad (inst.quad_box () & bbox, opt_bitmap, trans);
}
if (skip) {
// move on to the next quad
inst.skip_quad ();
continue;
}
if (last_ci != new_ci) {
// Hint: don't use any_cell_box on partially visible cells because that will degrade performance
if (new_cell_box.inside (*v)) {
@ -940,6 +1070,9 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
if (empty_inst_cell) {
lay::CanvasPlane *vertices = m_planes[3 + plane_group * (planes_per_layer / 3)];
r.draw (cell_inst.bbox (bc), trans, 0, 0, vertices, 0);
if (opt_bitmap) {
r.draw (cell_inst.bbox (bc), trans, opt_bitmap, 0, 0, 0);
}
}
lay::CanvasPlane *contour = m_planes[1 + plane_group * (planes_per_layer / 3)];
@ -955,9 +1088,10 @@ RedrawThreadWorker::draw_boxes_impl (bool drawing_context, db::cell_index_type c
for (db::CellInstArray::iterator p = cell_inst.begin_touching (*v, bc); ! p.at_end (); ) {
test_snapshot (0);
db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = safe_transformed_box (*v, t.inverted ());
draw_boxes_impl (drawing_context, new_ci, trans * t, new_vp, level + 1, for_ghosts);
draw_boxes_impl (drawing_context, new_ci, trans * t, new_vp, level + 1, for_ghosts, opt_bitmap);
if (p.quad_id () > 0 && p.quad_id () != qid) {
@ -1292,91 +1426,7 @@ RedrawThreadWorker::any_text_shapes (db::cell_index_type cell_index, unsigned in
return c->second;
}
static bool
has_zero_bit (const lay::Bitmap *bitmap, unsigned int ixmin, unsigned int iymin, unsigned int ixmax, unsigned int iymax)
{
uint32_t imin = ixmin / 32;
uint32_t imax = ixmax / 32;
if (imin == imax) {
uint32_t m = ((unsigned int) 0xffffffff << (ixmin % 32)) & ((unsigned int) 0xffffffff >> (31 - (ixmax % 32)));
for (unsigned int y = iymin; y <= iymax; ++y) {
if (bitmap->is_scanline_empty (y)) {
return true;
}
if ((bitmap->scanline (y) [imin] & m) != m) {
return true;
}
}
} else {
uint32_t m1 = ((unsigned int) 0xffffffff << (ixmin % 32));
uint32_t m2 = ((unsigned int) 0xffffffff >> (31 - (ixmax % 32)));
for (unsigned int y = iymin; y <= iymax; ++y) {
if (bitmap->is_scanline_empty (y)) {
return true;
}
if ((bitmap->scanline (y) [imin] & m1) != m1) {
return true;
}
for (unsigned int i = imin + 1; i < imax; ++i) {
if (bitmap->scanline (y) [i] != 0xffffffff) {
return true;
}
}
if ((bitmap->scanline (y) [imax] & m2) != m2) {
return true;
}
}
}
return false;
}
static bool
skip_quad (const db::Box &qb, const lay::Bitmap *vertex_bitmap, const db::CplxTrans &trans)
{
double threshold = 32 / trans.mag (); // don't check cells below 32x32 pixels
if (qb.empty () || qb.width () > threshold || qb.height () > threshold || !vertex_bitmap) {
return false;
}
db::DBox qb_trans = (trans * qb) & db::DBox (0, 0, vertex_bitmap->width () - 1.0 - 1e-6, vertex_bitmap->height () - 1.0 - 1e-6);
if (qb_trans.empty ()) {
return true;
}
int ixmin = (unsigned int)(qb_trans.left () + 0.5);
int ixmax = (unsigned int)(qb_trans.right () + 0.5);
int iymin = (unsigned int)(qb_trans.bottom () + 0.5);
int iymax = (unsigned int)(qb_trans.top () + 0.5);
if (! has_zero_bit (vertex_bitmap, ixmin, iymin, ixmax, iymax)) {
return true; // skip
} else {
return false;
}
}
inline void
copy_bitmap (const lay::Bitmap *from, lay::Bitmap *to, int dx, int dy)
{
if (to) {
to->merge (from, dx, dy);
}
}
std::vector<db::Box>
std::vector<db::Box>
RedrawThreadWorker::search_regions (const db::Box &cell_bbox, const db::Box &vp, int level)
{
std::vector<db::Box> vv;

View File

@ -185,13 +185,13 @@ private:
void draw_boxes_for_ghosts (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level);
void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level);
void draw_boxes_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level, bool for_ghosts);
void draw_boxes_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, bool for_ghosts);
void draw_boxes_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, bool for_ghosts, Bitmap *opt_bitmap);
void draw_box_properties_for_ghosts (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level);
void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level);
void draw_box_properties_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level, bool for_ghosts);
void draw_box_properties_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, int level, db::properties_id_type prop_id, bool for_ghosts);
void draw_box_properties_impl (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, db::properties_id_type prop_id, bool for_ghosts);
void draw_cell (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, bool empty_cell, const std::string &txt);
void draw_cell (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, const db::Box &box_for_label, bool empty_cell, const std::string &txt, Bitmap *opt_bitmap);
void draw_cell_properties (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, db::properties_id_type prop_id);
void draw_cell_shapes (const db::CplxTrans &trans, const db::Cell &cell, const db::Box &vp, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text);
void test_snapshot (const UpdateSnapshotCallback *update_snapshot);
@ -216,6 +216,7 @@ private:
int m_from_level, m_to_level;
int m_from_level_default, m_to_level_default;
int m_min_size_for_label;
double m_empty_cell_dimension;
bool m_box_text_transform;
unsigned int m_box_font;
unsigned int m_text_font;

View File

@ -91,6 +91,7 @@ static const std::string cfg_crosshair_cursor_enabled ("crosshair-cursor-enabled
static const std::string cfg_markers_visible ("markers-visible");
static const std::string cfg_min_inst_label_size ("min-inst-label-size");
static const std::string cfg_empty_cell_dimension ("empty-cell-dimension");
static const std::string cfg_cell_box_text_font ("inst-label-font");
static const std::string cfg_cell_box_text_transform ("inst-label-transform");
static const std::string cfg_cell_box_color ("inst-color");

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>656</width>
<height>397</height>
<height>451</height>
</rect>
</property>
<property name="windowTitle">
@ -49,85 +49,14 @@
<bool>false</bool>
</property>
<layout class="QGridLayout">
<property name="margin" stdset="0">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="1">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<item row="2" column="0">
<widget class="QLabel" name="textLabel1_3">
<property name="text">
<string>Label font</string>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="cell_font_cb"/>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>141</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="lay::ColorButton" name="cell_box_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
@ -190,6 +119,20 @@
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="textLabel3">
<property name="text">
<string>Cell box color</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="cell_xform_text_cbx">
<property name="text">
<string>Transform text with cell instance (not available for &quot;Default&quot; font)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="textLabel1_2_2">
<property name="text">
@ -197,21 +140,7 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="textLabel1_3">
<property name="text">
<string>Label font</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="textLabel3">
<property name="text">
<string>Cell box color</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -227,10 +156,139 @@
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="cell_xform_text_cbx">
<item row="3" column="1">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="lay::ColorButton" name="cell_box_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="cell_font_cb"/>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>141</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="empty_cell_dimension">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>µm (for label scaling)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>159</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Transform text with cell instance (not available for &quot;Default&quot; font)</string>
<string>Empty cell virtual size</string>
</property>
</widget>
</item>

View File

@ -227,6 +227,10 @@ LayoutViewConfigPage2a::setup (lay::Dispatcher *root)
root->config_get (cfg_min_inst_label_size, n);
mp_ui->cell_min_size_for_label_edit->setText (tl::to_qstring (tl::to_string (n)));
double ecd = 0;
root->config_get (cfg_empty_cell_dimension, ecd);
mp_ui->empty_cell_dimension->setText (tl::to_qstring (tl::to_string (ecd)));
bool gs_visible = true;
root->config_get (cfg_guiding_shape_visible, gs_visible);
mp_ui->pcell_gs_group->setChecked (gs_visible);
@ -263,6 +267,12 @@ LayoutViewConfigPage2a::commit (lay::Dispatcher *root)
tl::from_string_ext (tl::to_string (mp_ui->cell_min_size_for_label_edit->text ()), n);
root->config_set (cfg_min_inst_label_size, n);
} catch (...) { }
try {
double ecd;
tl::from_string_ext (tl::to_string (mp_ui->empty_cell_dimension->text ()), ecd);
root->config_set (cfg_empty_cell_dimension, ecd);
} catch (...) { }
}
// ------------------------------------------------------------