mirror of https://github.com/KLayout/klayout.git
Refactoring, preparing script generation.
This commit is contained in:
parent
637968cbc4
commit
6e6ce998aa
|
|
@ -628,9 +628,9 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
|
|||
origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons);
|
||||
}
|
||||
|
||||
DB_PUBLIC void
|
||||
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
|
||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
|
||||
static void
|
||||
fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
|
||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, int iteration)
|
||||
{
|
||||
if (row_step.x () <= 0 || column_step.y () <= 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row step must have a positive x component while column step must have a positive y component")));
|
||||
|
|
@ -642,11 +642,27 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
|
|||
|
||||
std::vector<db::Polygon> rem_pp, rem_poly;
|
||||
|
||||
size_t n = 0;
|
||||
for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) {
|
||||
if (!fill_region (cell, *p, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin)) {
|
||||
if (remaining_polygons) {
|
||||
rem_poly.push_back (*p);
|
||||
++n;
|
||||
}
|
||||
|
||||
{
|
||||
std::string progress_title;
|
||||
if (iteration > 0) {
|
||||
progress_title = tl::sprintf (tl::to_string (tr ("Fill polygons (iteration #%d)")), iteration);
|
||||
} else {
|
||||
progress_title = tl::sprintf (tl::to_string (tr ("Fill polygons")));
|
||||
}
|
||||
tl::RelativeProgress progress (progress_title, n);
|
||||
|
||||
for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) {
|
||||
if (!fill_region (cell, *p, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin)) {
|
||||
if (remaining_polygons) {
|
||||
rem_poly.push_back (*p);
|
||||
}
|
||||
}
|
||||
++progress;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -669,4 +685,35 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
|
|||
}
|
||||
}
|
||||
|
||||
DB_PUBLIC void
|
||||
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
|
||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons)
|
||||
{
|
||||
fill_region_impl (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons, 0);
|
||||
}
|
||||
|
||||
DB_PUBLIC void
|
||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
||||
const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons)
|
||||
{
|
||||
const db::Region *fill_region = &fr;
|
||||
|
||||
db::Region new_fill_region;
|
||||
db::Region remaining;
|
||||
|
||||
int iteration = 0;
|
||||
|
||||
while (! fill_region->empty ()) {
|
||||
|
||||
++iteration;
|
||||
|
||||
fill_region_impl (cell, *fill_region, fill_cell_index, kernel_origin, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration);
|
||||
|
||||
new_fill_region.swap (remaining);
|
||||
fill_region = &new_fill_region;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,5 +104,15 @@ DB_PUBLIC void
|
|||
fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
|
||||
db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0);
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief An iterative version for enhanced fill
|
||||
*
|
||||
* This version operates like the region-based fill_region version, but repeates the fill step until no further fill cells can be placed.
|
||||
* The remaining parts will be placed inside "remaining_polygons" unless this pointer is null.
|
||||
*/
|
||||
DB_PUBLIC void
|
||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
||||
const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons = 0);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1322,6 +1322,13 @@ fill_region2d (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_ce
|
|||
db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons)
|
||||
{
|
||||
db::fill_region_repeat (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons);
|
||||
}
|
||||
|
||||
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
|
|
@ -1802,7 +1809,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method_ext ("fill_region", &fill_region1d, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("kernel_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin"),
|
||||
"@brief Fills the given region with cells of the given type (diamond-shape fill kernel)\n"
|
||||
"@brief Fills the given region with cells of the given type (diamond fill kernel)\n"
|
||||
"@param region The region to fill\n"
|
||||
"@param fill_cell_index The fill cell to place\n"
|
||||
"@param kernel_origin The fill cell's footprint\n"
|
||||
|
|
@ -1860,7 +1867,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method_ext ("fill_region", &fill_region2d, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("kernel_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin"), gsi::arg ("remaining_parts"), gsi::arg ("fill_margin"), gsi::arg ("remaining_polygons"),
|
||||
"@brief Fills the given region with cells of the given type (diamond-shape fill kernel, extended version)\n"
|
||||
"@brief Fills the given region with cells of the given type (diamond fill kernel, extended version)\n"
|
||||
"@param region The region to fill\n"
|
||||
"@param fill_cell_index The fill cell to place\n"
|
||||
"@param kernel_origin The fill cell's footprint\n"
|
||||
|
|
@ -1877,6 +1884,14 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This variant has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("fill_region_multi", &fill_region_repeat, gsi::arg ("region"), gsi::arg ("fill_cell_index"), gsi::arg ("kernel_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("fill_margin"), gsi::arg ("remaining_polygons"),
|
||||
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
|
||||
"This version operates like \\fill_region, but repeates the fill generation until no further fill cells can be placed. "
|
||||
"As the fill pattern origin changes between the iterations, narrow regions can be filled which cannot with a fixed fill pattern origin. "
|
||||
"The \\fill_margin parameter is important as it controls the distance between fill cells with a different origin and therefore pitch-incompatible arrays.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_rec", &begin_shapes_rec, gsi::arg ("layer"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the cell on the given layer\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@
|
|||
<property name="windowTitle">
|
||||
<string>Fill Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
|
|
@ -29,7 +26,24 @@
|
|||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="generate_script_pb">
|
||||
<property name="text">
|
||||
<string>Generate Script Code</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
|
|
@ -969,16 +983,6 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@
|
|||
#include "antService.h"
|
||||
#include "tlException.h"
|
||||
#include "tlString.h"
|
||||
#include "layMainWindow.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "layMainWindow.h"
|
||||
#include "layCellSelectionForm.h"
|
||||
#include "edtService.h"
|
||||
|
||||
|
|
@ -134,66 +134,182 @@ FillDialog::choose_fc_2nd ()
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
collect_fill_regions (const db::Layout &layout,
|
||||
db::cell_index_type cell_index,
|
||||
unsigned int layer,
|
||||
const db::CplxTrans &trans,
|
||||
std::vector <db::Polygon> ®ions)
|
||||
void
|
||||
FillDialog::generate_fill (const FillParameters &fp)
|
||||
{
|
||||
const db::Cell &cell = layout.cell (cell_index);
|
||||
if (! cell.bbox (layer).empty ()) {
|
||||
|
||||
// any shapes to consider ..
|
||||
for (db::ShapeIterator sh = cell.shapes (layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes); ! sh.at_end (); ++sh) {
|
||||
regions.push_back (db::Polygon ());
|
||||
sh->polygon (regions.back ());
|
||||
}
|
||||
|
||||
for (db::Cell::const_iterator inst = cell.begin (); ! inst.at_end (); ++inst) {
|
||||
for (db::CellInstArray::iterator a = inst->cell_inst ().begin (); ! a.at_end (); ++a) {
|
||||
collect_fill_regions (layout, inst->cell_index (), layer, trans * inst->cell_inst ().complex_trans (*a), regions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
collect_fill_regions (const db::Layout &layout,
|
||||
db::cell_index_type cell_index,
|
||||
unsigned int layer,
|
||||
std::vector <db::Polygon> ®ions)
|
||||
{
|
||||
collect_fill_regions (layout, cell_index, layer, db::CplxTrans (), regions);
|
||||
}
|
||||
|
||||
void
|
||||
FillDialog::ok_pressed ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
if (tl::verbosity () >= 10) {
|
||||
tl::info << "Running fill";
|
||||
}
|
||||
|
||||
lay::CellView cv = mp_view->cellview (mp_view->active_cellview_index ());
|
||||
db::Layout &ly = cv->layout ();
|
||||
|
||||
std::vector <unsigned int> exclude_layers;
|
||||
|
||||
if (layer_spec_cbx->currentIndex () == 0) {
|
||||
|
||||
if (fp.exclude_all_layers) {
|
||||
// all layers
|
||||
for (db::Layout::layer_iterator l = cv->layout ().begin_layers (); l != cv->layout ().end_layers (); ++l) {
|
||||
for (db::Layout::layer_iterator l = ly.begin_layers (); l != ly.end_layers (); ++l) {
|
||||
exclude_layers.push_back ((*l).first);
|
||||
}
|
||||
} else {
|
||||
// some layers
|
||||
for (std::vector<db::LayerProperties>::const_iterator l = fp.exclude_layers.begin (); l != fp.exclude_layers.end (); ++l) {
|
||||
exclude_layers.push_back (ly.get_layer (*l));
|
||||
}
|
||||
}
|
||||
|
||||
bool enhanced_fill = enhanced_cb->isChecked ();
|
||||
|
||||
db::Coord exclude_x = db::coord_traits<db::Coord>::rounded (fp.exclude_distance.x () / ly.dbu ());
|
||||
db::Coord exclude_y = db::coord_traits<db::Coord>::rounded (fp.exclude_distance.y () / ly.dbu ());
|
||||
|
||||
db::Coord distance_x = db::coord_traits<db::Coord>::rounded (fp.border_distance.x () / ly.dbu ());
|
||||
db::Coord distance_y = db::coord_traits<db::Coord>::rounded (fp.border_distance.y () / ly.dbu ());
|
||||
|
||||
db::Vector fill_margin = db::CplxTrans (ly.dbu ()).inverted () * fp.fill_cell_margin;
|
||||
db::Vector fill_margin2 = db::CplxTrans (ly.dbu ()).inverted () * fp.fill_cell_margin2;
|
||||
|
||||
std::pair<bool, db::cell_index_type> fc = cv->layout ().cell_by_name (fp.fill_cell_name.c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Fill cell not found: ")) + fp.fill_cell_name);
|
||||
}
|
||||
|
||||
const db::Cell *fill_cell = &ly.cell (fc.second);
|
||||
|
||||
std::pair<bool, db::cell_index_type> fc2 = cv->layout ().cell_by_name (fp.fill_cell_name2.c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Secondary fill cell not found: ")) + fp.fill_cell_name2);
|
||||
}
|
||||
|
||||
const db::Cell *fill_cell2 = &ly.cell (fc2.second);
|
||||
|
||||
db::Vector row_step = db::CplxTrans (ly.dbu ()).inverted () * fp.row_step;
|
||||
db::Vector column_step = db::CplxTrans (ly.dbu ()).inverted () * fp.column_step;
|
||||
db::Vector kernel_origin = db::CplxTrans (ly.dbu ()).inverted () * fp.kernel_origin;
|
||||
|
||||
db::Vector row_step2 = db::CplxTrans (ly.dbu ()).inverted () * fp.row_step2;
|
||||
db::Vector column_step2 = db::CplxTrans (ly.dbu ()).inverted () * fp.column_step2;
|
||||
db::Vector kernel_origin2 = db::CplxTrans (ly.dbu ()).inverted () * fp.kernel_origin2;
|
||||
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Collecting fill regions";
|
||||
}
|
||||
|
||||
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Fill")));
|
||||
|
||||
db::Region fill_region;
|
||||
if (fp.fill_region_mode == FillParameters::Region) {
|
||||
fill_region = fp.fill_region;
|
||||
} else if (fp.fill_region_mode == FillParameters::WholeCell) {
|
||||
fill_region.insert (cv->layout ().cell (cv.cell_index ()).bbox ());
|
||||
} else if (fp.fill_region_mode == FillParameters::Layer) {
|
||||
unsigned int layer_index = cv->layout ().get_layer (fp.fill_region_layer);
|
||||
fill_region = db::Region (db::RecursiveShapeIterator (cv->layout (), *cv.cell (), layer_index));
|
||||
}
|
||||
|
||||
fill_region.enable_progress (tl::to_string (tr ("Computing fill region")));
|
||||
|
||||
if (! fill_region.empty ()) {
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Preprocessing fill regions";
|
||||
}
|
||||
|
||||
// preprocess fill regions
|
||||
if (distance_x != 0 || distance_y != 0) {
|
||||
fill_region.size (distance_x, distance_y);
|
||||
} else {
|
||||
fill_region.merge ();
|
||||
}
|
||||
|
||||
db::Box fr_bbox = fill_region.bbox ();
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Collecting exclude areas";
|
||||
}
|
||||
|
||||
// collect sized shapes from the exclude layers
|
||||
db::Region es;
|
||||
es.enable_progress (tl::to_string (tr ("Preparing exclude layers")));
|
||||
for (std::vector <unsigned int>::const_iterator l = exclude_layers.begin (); l != exclude_layers.end (); ++l) {
|
||||
|
||||
db::Region exclude (db::RecursiveShapeIterator (cv->layout (), *cv.cell (), *l));
|
||||
exclude.enable_progress (tl::to_string (tr ("Preparing exclude layer: ")) + cv->layout ().get_properties (*l).to_string ());
|
||||
|
||||
if (exclude_x != 0 || exclude_y != 0) {
|
||||
exclude.size (exclude_x, exclude_y);
|
||||
} else {
|
||||
exclude.merge ();
|
||||
}
|
||||
|
||||
es += exclude;
|
||||
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Computing effective fill region";
|
||||
}
|
||||
|
||||
// Perform the NOT operation to create the fill region
|
||||
fill_region -= es;
|
||||
|
||||
db::Region new_fill_area;
|
||||
|
||||
int step = 0;
|
||||
|
||||
do {
|
||||
|
||||
++step;
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Major iteration (primary/secondary fill cell)";
|
||||
}
|
||||
|
||||
if (! enhanced_fill) {
|
||||
db::fill_region (cv.cell (), fill_region, fill_cell->cell_index (), kernel_origin, row_step, column_step, fr_bbox.p1 (), false, fill_cell2 ? &fill_region : 0, fill_margin, fill_cell2 ? &fill_region : 0);
|
||||
} else {
|
||||
db::fill_region_repeat (cv.cell (), fill_region, fill_cell->cell_index (), kernel_origin, row_step, column_step, fill_margin, fill_cell2 ? &fill_region : 0);
|
||||
}
|
||||
|
||||
fill_cell = fill_cell2;
|
||||
row_step = row_step2;
|
||||
column_step = column_step2;
|
||||
kernel_origin = kernel_origin2;
|
||||
fill_margin = fill_margin2;
|
||||
|
||||
fill_cell2 = 0;
|
||||
|
||||
} while (fill_cell != 0 && ! fill_region.empty ());
|
||||
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Fill done";
|
||||
}
|
||||
}
|
||||
|
||||
FillParameters
|
||||
FillDialog::get_fill_parameters ()
|
||||
{
|
||||
FillParameters fp;
|
||||
|
||||
lay::CellView cv = mp_view->cellview (mp_view->active_cellview_index ());
|
||||
|
||||
fp.exclude_all_layers = false;
|
||||
|
||||
if (layer_spec_cbx->currentIndex () == 0) {
|
||||
|
||||
fp.exclude_all_layers = true;
|
||||
|
||||
} else if (layer_spec_cbx->currentIndex () == 1) {
|
||||
|
||||
// visible layers
|
||||
for (lay::LayerPropertiesConstIterator l = mp_view->begin_layers (); ! l.at_end (); ++l) {
|
||||
if (! l->has_children () && l->visible (true)) {
|
||||
exclude_layers.push_back (l->layer_index ());
|
||||
fp.exclude_layers.push_back (cv->layout ().get_properties (l->layer_index ()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +319,7 @@ BEGIN_PROTECTED
|
|||
std::vector<lay::LayerPropertiesConstIterator> s = mp_view->selected_layers ();
|
||||
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = s.begin (); l != s.end (); ++l) {
|
||||
if (! (*l)->has_children ()) {
|
||||
exclude_layers.push_back ((*l)->layer_index ());
|
||||
fp.exclude_layers.push_back (cv->layout ().get_properties ((*l)->layer_index ()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,139 +337,14 @@ BEGIN_PROTECTED
|
|||
}
|
||||
}
|
||||
|
||||
db::Coord exclude_x = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
db::Coord exclude_y = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
|
||||
// read distance to border
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (distance_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
|
||||
db::Coord distance_x = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
db::Coord distance_y = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
|
||||
// read fill cell margin
|
||||
db::Vector fill_margin;
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (fill_margin_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
fill_margin = db::Vector (db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ()), db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ()));
|
||||
}
|
||||
|
||||
// read fill cell 2 margin
|
||||
db::Vector fill2_margin;
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (fill2_margin_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
fill2_margin = db::Vector (db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ()), db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ()));
|
||||
}
|
||||
|
||||
// get the fill cell
|
||||
std::pair<bool, db::cell_index_type> fc = cv->layout ().cell_by_name (tl::to_string (fill_cell_le->text ()).c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Fill cell not found: ")) + tl::to_string (fill_cell_le->text ()));
|
||||
}
|
||||
|
||||
const db::Cell *fill_cell = &cv->layout ().cell (fc.second);
|
||||
|
||||
int fc_bbox_layer = fc_boundary_layer->current_layer ();
|
||||
if (fc_bbox_layer >= 0 && ! cv->layout ().is_valid_layer (fc_bbox_layer)) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from")));
|
||||
}
|
||||
|
||||
db::Box fc_bbox = fc_bbox_layer < 0 ? fill_cell->bbox () : fill_cell->bbox (fc_bbox_layer);
|
||||
if (fc_bbox.empty ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from - layer is empty for the fill cell")));
|
||||
}
|
||||
|
||||
db::Coord row_dx = fc_bbox.width (), row_dy = 0;
|
||||
db::Coord column_dx = 0.0, column_dy = fc_bbox.height ();
|
||||
|
||||
s = tl::to_string (row_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
row_dx = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
row_dy = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
}
|
||||
|
||||
s = tl::to_string (column_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
column_dx = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
column_dy = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
}
|
||||
|
||||
bool enhanced_fill = enhanced_cb->isChecked ();
|
||||
|
||||
double row_dx2 = 0.0, row_dy2 = 0.0;
|
||||
double column_dx2 = 0.0, column_dy2 = 0.0;
|
||||
|
||||
const db::Cell *fill_cell2 = 0;
|
||||
db::Box fc_bbox2;
|
||||
|
||||
if (second_order_fill_cb->isChecked ()) {
|
||||
|
||||
std::pair<bool, db::cell_index_type> fc = cv->layout ().cell_by_name (tl::to_string (fill_cell_2nd_le->text ()).c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Second order fill cell not found: ")) + tl::to_string (fill_cell_2nd_le->text ()));
|
||||
}
|
||||
|
||||
fill_cell2 = &cv->layout ().cell (fc.second);
|
||||
|
||||
fc_bbox2 = fc_bbox_layer < 0 ? fill_cell2->bbox () : fill_cell2->bbox (fc_bbox_layer);
|
||||
if (fc_bbox2.empty ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Second order fill cell is empty for the given boundary layer")));
|
||||
}
|
||||
|
||||
row_dx2 = fc_bbox2.width ();
|
||||
row_dy2 = 0;
|
||||
column_dx2 = 0.0;
|
||||
column_dy2 = fc_bbox2.height ();
|
||||
|
||||
s = tl::to_string (row_2nd_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
row_dx2 = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
row_dy2 = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
}
|
||||
|
||||
s = tl::to_string (column_2nd_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
column_dx2 = db::coord_traits<db::Coord>::rounded (x / cv->layout ().dbu ());
|
||||
column_dy2 = db::coord_traits<db::Coord>::rounded (y / cv->layout ().dbu ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Collecting fill regions";
|
||||
}
|
||||
fp.exclude_distance = db::DVector (x, y);
|
||||
|
||||
// get the fill regions
|
||||
std::vector <db::Polygon> fill_regions;
|
||||
|
||||
if (fill_area_cbx->currentIndex () == 3) {
|
||||
|
||||
fp.fill_region_mode = FillParameters::Region;
|
||||
|
||||
// explicit fill box
|
||||
|
||||
if (le_x1->text ().isEmpty () || le_x2->text ().isEmpty () ||
|
||||
|
|
@ -368,23 +359,27 @@ BEGIN_PROTECTED
|
|||
tl::from_string (tl::to_string (le_y1->text ()), y1);
|
||||
tl::from_string (tl::to_string (le_y2->text ()), y2);
|
||||
|
||||
fill_regions.push_back (db::Polygon (db::Box (db::DBox (db::DPoint (x1, y1), db::DPoint (x2, y2)) * (1.0 / cv->layout ().dbu ()))));
|
||||
fp.fill_region.insert (db::Box (db::DBox (db::DPoint (x1, y1), db::DPoint (x2, y2)) * (1.0 / cv->layout ().dbu ())));
|
||||
|
||||
} else if (fill_area_cbx->currentIndex () == 4) {
|
||||
|
||||
fp.fill_region_mode = FillParameters::Region;
|
||||
|
||||
// ruler
|
||||
|
||||
ant::Service *ant_service = mp_view->get_plugin <ant::Service> ();
|
||||
if (ant_service) {
|
||||
ant::AnnotationIterator ant = ant_service->begin_annotations ();
|
||||
while (! ant.at_end ()) {
|
||||
fill_regions.push_back (db::Polygon (db::Box (db::DBox (ant->p1 (), ant->p2 ()) * (1.0 / cv->layout ().dbu ()))));
|
||||
fp.fill_region.insert (db::Box (db::DBox (ant->p1 (), ant->p2 ()) * (1.0 / cv->layout ().dbu ())));
|
||||
++ant;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (fill_area_cbx->currentIndex () == 1) {
|
||||
|
||||
fp.fill_region_mode = FillParameters::Layer;
|
||||
|
||||
// specified layer
|
||||
|
||||
int sel_layer = cb_layer->current_layer ();
|
||||
|
|
@ -392,182 +387,169 @@ BEGIN_PROTECTED
|
|||
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill regions from")));
|
||||
}
|
||||
|
||||
collect_fill_regions (cv->layout (), cv.cell_index (), (unsigned int) sel_layer, fill_regions);
|
||||
fp.fill_region_layer = cv->layout ().get_properties (sel_layer);
|
||||
|
||||
} else if (fill_area_cbx->currentIndex () == 0) {
|
||||
|
||||
// whole cell
|
||||
fill_regions.push_back (db::Polygon (cv.cell ()->bbox ()));
|
||||
fp.fill_region_mode = FillParameters::WholeCell;
|
||||
|
||||
} else if (fill_area_cbx->currentIndex () == 2) {
|
||||
|
||||
fp.fill_region_mode = FillParameters::Region;
|
||||
|
||||
// selection
|
||||
std::vector<edt::Service *> edt_services = mp_view->get_plugins <edt::Service> ();
|
||||
for (std::vector<edt::Service *>::const_iterator s = edt_services.begin (); s != edt_services.end (); ++s) {
|
||||
for (edt::Service::objects::const_iterator sel = (*s)->selection ().begin (); sel != (*s)->selection ().end (); ++sel) {
|
||||
if (! sel->is_cell_inst () && (sel->shape ().is_polygon () || sel->shape ().is_path () || sel->shape ().is_box ())) {
|
||||
fill_regions.push_back (db::Polygon ());
|
||||
sel->shape ().polygon (fill_regions.back ());
|
||||
db::Polygon poly;
|
||||
sel->shape ().polygon (poly);
|
||||
fp.fill_region.insert (poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// read distance to border
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (distance_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
|
||||
fp.border_distance = db::DVector (x, y);
|
||||
|
||||
// read fill cell margin
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (fill_margin_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
|
||||
fp.fill_cell_margin = db::DVector (x, y);
|
||||
|
||||
// read fill cell 2 margin
|
||||
x = 0.0, y = 0.0;
|
||||
s = tl::to_string (fill2_margin_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x)) {
|
||||
if (ex.test (",") && ex.try_read (y)) {
|
||||
// take x, y
|
||||
} else {
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
|
||||
fp.fill_cell_margin2 = db::DVector (x, y);
|
||||
|
||||
fp.fill_cell_name = tl::to_string (fill_cell_le->text ());
|
||||
|
||||
// get the fill cell
|
||||
std::pair<bool, db::cell_index_type> fc = cv->layout ().cell_by_name (fp.fill_cell_name.c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Fill cell not found: ")) + tl::to_string (fill_cell_le->text ()));
|
||||
}
|
||||
|
||||
const db::Cell *fill_cell = &cv->layout ().cell (fc.second);
|
||||
|
||||
int fc_bbox_layer = fc_boundary_layer->current_layer ();
|
||||
if (fc_bbox_layer >= 0 && ! cv->layout ().is_valid_layer (fc_bbox_layer)) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from")));
|
||||
}
|
||||
|
||||
fp.enhanced_fill = enhanced_cb->isChecked ();
|
||||
|
||||
db::DBox fc_bbox = db::CplxTrans (cv->layout ().dbu ()) * (fc_bbox_layer < 0 ? fill_cell->bbox () : fill_cell->bbox (fc_bbox_layer));
|
||||
if (fc_bbox.empty ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from - layer is empty for the fill cell")));
|
||||
}
|
||||
|
||||
s = tl::to_string (row_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
fp.row_step = db::DVector (x, y);
|
||||
} else {
|
||||
fp.row_step = db::DVector (fc_bbox.width (), 0.0);
|
||||
}
|
||||
|
||||
s = tl::to_string (column_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
fp.column_step = db::DVector (x, y);
|
||||
} else {
|
||||
fp.column_step = db::DVector (0.0, fc_bbox.height ());
|
||||
}
|
||||
|
||||
fp.kernel_origin = fc_bbox.p1 () - db::DPoint ();
|
||||
|
||||
const db::Cell *fill_cell2 = 0;
|
||||
db::DBox fc_bbox2;
|
||||
|
||||
if (second_order_fill_cb->isChecked ()) {
|
||||
|
||||
fp.fill_cell_name2 = tl::to_string (fill_cell_2nd_le->text ());
|
||||
|
||||
std::pair<bool, db::cell_index_type> fc = cv->layout ().cell_by_name (fp.fill_cell_name2.c_str ());
|
||||
if (! fc.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Second order fill cell not found: ")) + tl::to_string (fill_cell_2nd_le->text ()));
|
||||
}
|
||||
|
||||
fill_cell2 = &cv->layout ().cell (fc.second);
|
||||
|
||||
fc_bbox2 = db::CplxTrans (cv->layout ().dbu ()) * (fc_bbox_layer < 0 ? fill_cell2->bbox () : fill_cell2->bbox (fc_bbox_layer));
|
||||
if (fc_bbox2.empty ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Second order fill cell is empty for the given boundary layer")));
|
||||
}
|
||||
|
||||
s = tl::to_string (row_2nd_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
fp.row_step2 = db::DVector (x, y);
|
||||
} else {
|
||||
fp.row_step2 = db::DVector (fc_bbox2.width (), 0.0);
|
||||
}
|
||||
|
||||
s = tl::to_string (column_2nd_le->text ());
|
||||
ex = tl::Extractor (s.c_str ());
|
||||
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
|
||||
fp.column_step2 = db::DVector (x, y);
|
||||
} else {
|
||||
fp.column_step2 = db::DVector (0.0, fc_bbox2.height ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
void
|
||||
FillDialog::ok_pressed ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
FillParameters fp = get_fill_parameters ();
|
||||
|
||||
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Fill")));
|
||||
|
||||
if (! fill_regions.empty ()) {
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Preprocessing fill regions";
|
||||
}
|
||||
|
||||
// TODO: progress
|
||||
|
||||
// preprocess fill regions
|
||||
if (distance_x != 0 || distance_y != 0) {
|
||||
|
||||
std::vector <db::Polygon> fp;
|
||||
ep.enable_progress (tl::to_string (QObject::tr ("Preparing fill regions")));
|
||||
ep.size (fill_regions, -distance_x, -distance_y, fp, 2 /*mode*/, false /*=don't resolve holes*/);
|
||||
ep.disable_progress ();
|
||||
|
||||
fill_regions.swap (fp);
|
||||
|
||||
}
|
||||
|
||||
std::sort (fill_regions.begin (), fill_regions.end ());
|
||||
fill_regions.erase (std::unique (fill_regions.begin (), fill_regions.end ()), fill_regions.end ());
|
||||
|
||||
// determine the fill region's bbox for selectively getting the exclude shapes
|
||||
db::Box fr_bbox;
|
||||
for (std::vector <db::Polygon>::const_iterator fr = fill_regions.begin (); fr != fill_regions.end (); ++fr) {
|
||||
fr_bbox += fr->box ();
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Collecting exclude areas";
|
||||
}
|
||||
|
||||
// collect sized shapes from the exclude layers
|
||||
std::vector <db::Polygon> es;
|
||||
for (std::vector <unsigned int>::const_iterator l = exclude_layers.begin (); l != exclude_layers.end (); ++l) {
|
||||
|
||||
std::vector <db::Polygon> shapes;
|
||||
|
||||
size_t n = 0;
|
||||
for (db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), *l); ! si.at_end (); ++si) {
|
||||
if (si->is_polygon () || si->is_path () || si->is_box ()) {
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
shapes.reserve (n);
|
||||
|
||||
for (db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), *l); ! si.at_end (); ++si) {
|
||||
if (si->is_polygon () || si->is_path () || si->is_box ()) {
|
||||
shapes.push_back (db::Polygon ());
|
||||
si->polygon (shapes.back ());
|
||||
shapes.back ().transform (si.trans ());
|
||||
}
|
||||
}
|
||||
|
||||
ep.enable_progress (tl::to_string (QObject::tr ("Preparing exclude regions")));
|
||||
ep.size (shapes, exclude_x, exclude_y, es, 2 /*mode*/, false /*=don't resolve holes*/);
|
||||
ep.disable_progress ();
|
||||
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Computing effective fill region";
|
||||
}
|
||||
|
||||
// Perform the NOT operation to create the fill region
|
||||
std::vector <db::Polygon> fill_area;
|
||||
ep.enable_progress (tl::to_string (QObject::tr ("Computing fill region")));
|
||||
ep.boolean (fill_regions, es, fill_area, db::BooleanOp::ANotB, false /*=don't resolve holes*/);
|
||||
ep.disable_progress ();
|
||||
|
||||
std::vector <db::Polygon> new_fill_area;
|
||||
|
||||
int step = 0;
|
||||
|
||||
do {
|
||||
|
||||
++step;
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Major iteration (primary/secondary fill cell)";
|
||||
}
|
||||
|
||||
std::vector <db::Polygon> non_filled_area;
|
||||
|
||||
int iteration = 0;
|
||||
|
||||
do {
|
||||
|
||||
++iteration;
|
||||
|
||||
if (tl::verbosity () >= 20 && enhanced_fill) {
|
||||
tl::info << "Minor iteration (enhanced fill)";
|
||||
}
|
||||
|
||||
tl::RelativeProgress progress (tl::sprintf (tl::to_string (QObject::tr ("Fill iteration %d (%s fill step)")), iteration, step == 1 ? tl::to_string (QObject::tr ("primary")) : tl::to_string (QObject::tr ("secondary"))), fill_area.size (), 10);
|
||||
|
||||
new_fill_area.clear ();
|
||||
|
||||
for (std::vector <db::Polygon>::const_iterator fp0 = fill_area.begin (); fp0 != fill_area.end (); ++fp0) {
|
||||
|
||||
if (tl::verbosity () >= 30) {
|
||||
tl::info << "Compute fill for one region :" << fp0->to_string ();
|
||||
}
|
||||
|
||||
db::Vector rs (row_dx, row_dy), cs (column_dx, column_dy);
|
||||
db::Vector ko = fc_bbox.center () - db::Point (row_dx / 2, column_dy / 2);
|
||||
|
||||
bool any_fill = fill_region (cv.cell (), *fp0, fill_cell->cell_index (), ko, rs, cs, fr_bbox.p1 (), enhanced_fill, (enhanced_fill || fill_cell2) ? &new_fill_area : 0, fill_margin);
|
||||
if (! any_fill) {
|
||||
non_filled_area.push_back (*fp0);
|
||||
}
|
||||
|
||||
++progress;
|
||||
|
||||
}
|
||||
|
||||
fill_area.swap (new_fill_area);
|
||||
|
||||
} while (enhanced_fill && ! fill_area.empty ());
|
||||
|
||||
if (fill_area.empty ()) {
|
||||
fill_area.swap (non_filled_area);
|
||||
} else if (fill_cell2) {
|
||||
fill_area.insert (fill_area.end (), non_filled_area.begin (), non_filled_area.end ());
|
||||
}
|
||||
|
||||
fill_cell = fill_cell2;
|
||||
fc_bbox = fc_bbox2;
|
||||
fill_margin = fill2_margin;
|
||||
|
||||
row_dx = row_dx2;
|
||||
row_dy = row_dy2;
|
||||
column_dx = column_dx2;
|
||||
column_dy = column_dy2;
|
||||
|
||||
fill_cell2 = 0;
|
||||
fc_bbox2 = db::Box ();
|
||||
|
||||
} while (fill_cell != 0 && ! fill_area.empty ());
|
||||
|
||||
try {
|
||||
generate_fill (fp);
|
||||
mp_view->manager ()->commit ();
|
||||
} catch (...) {
|
||||
mp_view->manager ()->cancel ();
|
||||
throw;
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Fill done";
|
||||
}
|
||||
|
||||
mp_view->manager ()->commit ();
|
||||
|
||||
// close this dialog
|
||||
QDialog::accept ();
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,44 @@
|
|||
#include "layLayoutView.h"
|
||||
#include "layPlugin.h"
|
||||
#include "layMarker.h"
|
||||
#include "layCommon.h"
|
||||
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class FillDialog
|
||||
struct LAY_PUBLIC FillParameters
|
||||
{
|
||||
FillParameters ()
|
||||
: exclude_all_layers (true), fill_region_mode (WholeCell), enhanced_fill (false)
|
||||
{ }
|
||||
|
||||
enum FillRegionMode {
|
||||
WholeCell,
|
||||
Region,
|
||||
Layer
|
||||
};
|
||||
|
||||
bool exclude_all_layers;
|
||||
std::vector<db::LayerProperties> exclude_layers;
|
||||
FillRegionMode fill_region_mode;
|
||||
db::Region fill_region;
|
||||
db::LayerProperties fill_region_layer;
|
||||
db::DVector exclude_distance;
|
||||
db::DVector border_distance;
|
||||
bool enhanced_fill;
|
||||
std::string fill_cell_name;
|
||||
db::DVector fill_cell_margin;
|
||||
db::DVector kernel_origin, row_step, column_step;
|
||||
std::string fill_cell_name2;
|
||||
db::DVector fill_cell_margin2;
|
||||
db::DVector kernel_origin2, row_step2, column_step2;
|
||||
};
|
||||
|
||||
class LAY_PUBLIC FillDialog
|
||||
: public QDialog,
|
||||
public lay::Plugin,
|
||||
private Ui::FillDialog
|
||||
|
|
@ -59,6 +90,9 @@ private:
|
|||
// implementation of the lay::Plugin interface
|
||||
void menu_activated (const std::string &symbol);
|
||||
|
||||
void generate_fill (const FillParameters &fp);
|
||||
FillParameters get_fill_parameters ();
|
||||
|
||||
lay::LayoutView *mp_view;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue