Merge branch 'master' of github.com:KLayout/klayout

This commit is contained in:
Matthias Koefferlein 2025-04-27 14:44:32 +02:00
commit 9c7ccefc9f
20 changed files with 455 additions and 274 deletions

View File

@ -547,7 +547,7 @@ drop_method "QDebug", /QDebug::operator\s*<<\((?!const\s+QString\s*&)/ # don't m
drop_method "", /::operator\s*<<\(QDebug\s*\w*\s*,\s*(?!const\s+QString\s*&)/ # don't map the others right now - too many (TODO: how to map?)
drop_method "QNoDebug", /QNoDebug::operator<</ # nothing usable (TODO: how to map?)
# No longer supported operator== and operator!= in Qt 6.7/6.8
# No longer supported operator== and operator!= in Qt 6.7/6.8/6.9
add_native_operator_neq(self, "QEasingCurve")
add_native_operator_neq(self, "QTimeZone")
add_native_operator_neq(self, "QDir")
@ -569,6 +569,7 @@ add_native_operator_neq(self, "QProcessEnvironment")
add_native_operator_neq(self, "QRegularExpression")
add_native_operator_neqlt(self, "QUrl")
add_native_operator_neq(self, "QUrlQuery")
add_native_operator_neq(self, "QDomNodeList")
add_native_operator_neq(self, "QXmlStreamAttribute")
add_native_operator_neq(self, "QXmlStreamEntityDeclaration")
add_native_operator_neq(self, "QXmlStreamNamespaceDeclaration")

View File

@ -1321,7 +1321,7 @@ struct edge_xmin_at_yinterval_double_compare
{
if (edge_xmax (a) < edge_xmin (b)) {
return true;
} else if (edge_xmin (a) >= edge_xmax (b)) {
} else if (edge_xmin (a) > edge_xmax (b)) {
return false;
} else {
C xa = edge_xmin_at_yinterval_double (a, m_y1, m_y2);

View File

@ -39,7 +39,9 @@ PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db
void PolygonRefToShapesGenerator::put (const db::Polygon &polygon)
{
tl::MutexLocker locker (&mp_layout->lock ());
if (m_prop_id != 0) {
if (polygon.is_empty ()) {
// ignore empty polygons
} else if (m_prop_id != 0) {
mp_shapes->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
} else {
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
@ -58,7 +60,9 @@ PolygonSplitter::PolygonSplitter (PolygonSink &sink, double max_area_ratio, size
void
PolygonSplitter::put (const db::Polygon &poly)
{
if (db::suggest_split_polygon (poly, m_max_vertex_count, m_max_area_ratio)) {
if (poly.is_empty ()) {
// ignore empty polygons
} else if (db::suggest_split_polygon (poly, m_max_vertex_count, m_max_area_ratio)) {
std::vector <db::Polygon> split_polygons;
db::split_polygon (poly, split_polygons);

View File

@ -1771,6 +1771,14 @@ public:
return true;
}
/**
* @brief Returns a value indicating that the polygon is an empty one
*/
bool is_empty () const
{
return m_ctrs.size () == size_t (1) && m_ctrs[0].size () == 0;
}
/**
* @brief Returns the number of points in the polygon
*/
@ -1879,6 +1887,7 @@ public:
for (typename contour_list_type::iterator h = m_ctrs.begin (); h != m_ctrs.end (); ++h) {
h->transform (db::unit_trans<C> (), true /*compress*/, remove_reflected);
}
m_bbox = m_ctrs [0].bbox ();
return *this;
}
@ -2804,6 +2813,7 @@ public:
{
// compress the polygon by employing the transform method
m_hull.transform (db::unit_trans<C> (), true, remove_reflected);
m_bbox = m_hull.bbox ();
return *this;
}
@ -3022,6 +3032,14 @@ public:
return m_hull.is_halfmanhattan ();
}
/**
* @brief Returns a value indicating that the polygon is an empty one
*/
bool is_empty () const
{
return m_hull.size () == 0;
}
/**
* @brief The number of holes
*

View File

@ -1618,18 +1618,34 @@ bool_and_or_not_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layou
}
}
db::polygon_ref_generator<TR> pr (layout, result);
db::PolygonSplitter splitter (pr, proc->area_ratio (), proc->max_vertex_count ());
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
const TR &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
// shortcut (and: keep, not: drop)
// Note that we still normalize and split the polygon, so we get a uniform
// behavior.
if (m_is_and) {
result.insert (subject);
db::Polygon poly;
subject.instantiate (poly);
splitter.put (poly);
}
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
// Note that we still normalize and split the polygon, so we get a uniform
// behavior.
if (! m_is_and) {
result.insert (subject);
db::Polygon poly;
subject.instantiate (poly);
splitter.put (poly);
}
} else {
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
@ -1649,8 +1665,6 @@ bool_and_or_not_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layou
}
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
db::polygon_ref_generator<TR> pr (layout, result);
db::PolygonSplitter splitter (pr, proc->area_ratio (), proc->max_vertex_count ());
db::PolygonGenerator pg (splitter, true, true);
ep.set_base_verbosity (50);
ep.process (pg, op);

View File

@ -69,6 +69,7 @@ TEST(1)
EXPECT_EQ (empty == p, true);
EXPECT_EQ (p.is_box (), false);
EXPECT_EQ (p.is_empty (), true);
std::vector <db::Point> c1, c2, c3;
c1.push_back (db::Point (0, 0));
@ -76,6 +77,7 @@ TEST(1)
c1.push_back (db::Point (100, 1000));
c1.push_back (db::Point (100, 0));
p.assign_hull (c1.begin (), c1.end ());
EXPECT_EQ (p.is_empty (), false);
b = p.box ();
EXPECT_EQ (p.holes (), size_t (0));
EXPECT_EQ (p.area (), 1000*100);
@ -1404,3 +1406,30 @@ TEST(28)
db::Polygon b (db::Box (-1000000000, -1000000000, 1000000000, 1000000000));
EXPECT_EQ (b.perimeter (), 8000000000.0);
}
TEST(29)
{
// Degenerated boxes and compress
db::Polygon b (db::Box (10, 20, 10, 20));
EXPECT_EQ (b.is_empty (), false);
EXPECT_EQ (b == db::Polygon (), false);
EXPECT_EQ (b.to_string (), "(10,20;10,20;10,20;10,20)");
EXPECT_EQ (double (b.area ()), 0.0);
b.compress (true);
EXPECT_EQ (b.is_empty (), true);
EXPECT_EQ (b == db::Polygon (), true);
db::SimplePolygon sb (db::Box (10, 20, 10, 20));
EXPECT_EQ (sb.is_empty (), false);
EXPECT_EQ (sb == db::SimplePolygon (), false);
EXPECT_EQ (sb.to_string (), "(10,20;10,20;10,20;10,20)");
EXPECT_EQ (double (sb.area ()), 0.0);
sb.compress (true);
EXPECT_EQ (sb.is_empty (), true);
EXPECT_EQ (sb == db::SimplePolygon (), true);
}

View File

@ -1585,7 +1585,8 @@ module DRC
self._context("report") do
# finish what we got so far
_finish(false)
view = RBA::LayoutView::current
@def_output && @def_output.finish(false, view)
@def_output = nil
@def_output = _make_report(description, filename, cellname)

View File

@ -1694,6 +1694,16 @@ TEST(93d_withAngle)
run_test (_this, "93", true);
}
TEST(94_texts_in_region_xor)
{
run_test (_this, "94", false);
}
TEST(94d_texts_in_region_xor)
{
run_test (_this, "94", true);
}
TEST(100_edge_interaction_with_count)
{
run_test (_this, "100", false);

View File

@ -47,6 +47,31 @@
namespace edt
{
static std::string variant_list_to_string (const tl::Variant &value)
{
if (! value.is_list ()) {
tl::Variant v = tl::Variant::empty_list ();
v.push (value);
return v.to_parsable_string ();
}
for (auto i = value.begin (); i != value.end (); ++i) {
if (! i->is_a_string () || std::string (i->to_string ()).find (",") != std::string::npos) {
return value.to_parsable_string ();
}
}
// otherwise we can plainly combine the strings with ","
std::string res;
for (auto i = value.begin (); i != value.end (); ++i) {
if (i != value.begin ()) {
res += ",";
}
res += i->to_string ();
}
return res;
}
static void set_value (const db::PCellParameterDeclaration &p, QWidget *widget, const tl::Variant &value)
{
if (p.get_choices ().empty ()) {
@ -91,7 +116,7 @@ static void set_value (const db::PCellParameterDeclaration &p, QWidget *widget,
QLineEdit *le = dynamic_cast<QLineEdit *> (widget);
if (le) {
le->blockSignals (true);
le->setText (value.to_qstring ());
le->setText (tl::to_qstring (variant_list_to_string (value)));
le->blockSignals (false);
}
}
@ -905,8 +930,29 @@ PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
std::vector<std::string> values = tl::split (tl::to_string (le->text ()), ",");
std::string s = tl::to_string (le->text ());
// try parsing a bracketed expression
tl::Extractor ex (s.c_str ());
if (*ex.skip () == '(') {
tl::Variant v;
try {
ex.read (v);
ps.set_value (v);
break;
} catch (...) {
// ignore errors
}
} else if (ex.at_end ()) {
ps.set_value (tl::Variant::empty_list ());
break;
}
// otherwise: plain splitting at comma
std::vector<std::string> values = tl::split (s, ",");
ps.set_value (tl::Variant (values.begin (), values.end ()));
}
}
break;

View File

@ -35,6 +35,12 @@
// -----------------------------------------------------------------------
// class QDomNodeList
static bool QDomNodeList_operator_eq(const QDomNodeList *a, const QDomNodeList &b) {
return *a == b;
}
static bool QDomNodeList_operator_ne(const QDomNodeList *a, const QDomNodeList &b) {
return !(*a == b);
}
// Constructor QDomNodeList::QDomNodeList()
@ -153,25 +159,6 @@ static void _call_f_length_c0 (const qt_gsi::GenericMethod * /*decl*/, void *cls
}
// bool QDomNodeList::operator!=(const QDomNodeList &)
static void _init_f_operator_excl__eq__c2484 (qt_gsi::GenericMethod *decl)
{
static gsi::ArgSpecBase argspec_0 ("arg1");
decl->add_arg<const QDomNodeList & > (argspec_0);
decl->set_return<bool > ();
}
static void _call_f_operator_excl__eq__c2484 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
{
__SUPPRESS_UNUSED_WARNING(args);
tl::Heap heap;
const QDomNodeList &arg1 = gsi::arg_reader<const QDomNodeList & >() (args, heap);
ret.write<bool > ((bool)((QDomNodeList *)cls)->operator!= (arg1));
}
// QDomNodeList &QDomNodeList::operator=(const QDomNodeList &)
@ -191,25 +178,6 @@ static void _call_f_operator_eq__2484 (const qt_gsi::GenericMethod * /*decl*/, v
}
// bool QDomNodeList::operator==(const QDomNodeList &)
static void _init_f_operator_eq__eq__c2484 (qt_gsi::GenericMethod *decl)
{
static gsi::ArgSpecBase argspec_0 ("arg1");
decl->add_arg<const QDomNodeList & > (argspec_0);
decl->set_return<bool > ();
}
static void _call_f_operator_eq__eq__c2484 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
{
__SUPPRESS_UNUSED_WARNING(args);
tl::Heap heap;
const QDomNodeList &arg1 = gsi::arg_reader<const QDomNodeList & >() (args, heap);
ret.write<bool > ((bool)((QDomNodeList *)cls)->operator== (arg1));
}
// int QDomNodeList::size()
@ -238,14 +206,15 @@ static gsi::Methods methods_QDomNodeList () {
methods += new qt_gsi::GenericMethod ("isEmpty?", "@brief Method bool QDomNodeList::isEmpty()\n", true, &_init_f_isEmpty_c0, &_call_f_isEmpty_c0);
methods += new qt_gsi::GenericMethod ("item", "@brief Method QDomNode QDomNodeList::item(int index)\n", true, &_init_f_item_c767, &_call_f_item_c767);
methods += new qt_gsi::GenericMethod ("length", "@brief Method int QDomNodeList::length()\n", true, &_init_f_length_c0, &_call_f_length_c0);
methods += new qt_gsi::GenericMethod ("!=", "@brief Method bool QDomNodeList::operator!=(const QDomNodeList &)\n", true, &_init_f_operator_excl__eq__c2484, &_call_f_operator_excl__eq__c2484);
methods += new qt_gsi::GenericMethod ("assign", "@brief Method QDomNodeList &QDomNodeList::operator=(const QDomNodeList &)\n", false, &_init_f_operator_eq__2484, &_call_f_operator_eq__2484);
methods += new qt_gsi::GenericMethod ("==", "@brief Method bool QDomNodeList::operator==(const QDomNodeList &)\n", true, &_init_f_operator_eq__eq__c2484, &_call_f_operator_eq__eq__c2484);
methods += new qt_gsi::GenericMethod ("size", "@brief Method int QDomNodeList::size()\n", true, &_init_f_size_c0, &_call_f_size_c0);
return methods;
}
gsi::Class<QDomNodeList> decl_QDomNodeList ("QtXml", "QDomNodeList",
gsi::method_ext("==", &QDomNodeList_operator_eq, gsi::arg ("other"), "@brief Method bool QDomNodeList::operator==(const QDomNodeList &) const") +
gsi::method_ext("!=", &QDomNodeList_operator_ne, gsi::arg ("other"), "@brief Method bool QDomNodeList::operator!=(const QDomNodeList &) const")
+
methods_QDomNodeList (),
"@qt\n@brief Binding of QDomNodeList");

View File

@ -43,6 +43,7 @@ static const std::string cfg_grid_grid_color ("grid-grid-color");
static const std::string cfg_grid_style0 ("grid-style0");
static const std::string cfg_grid_style1 ("grid-style1");
static const std::string cfg_grid_style2 ("grid-style2");
static const std::string cfg_grid_density ("grid-density");
static const std::string cfg_grid_visible ("grid-visible");
static const std::string cfg_grid_micron ("grid-micron");
static const std::string cfg_grid_show_ruler ("grid-show-ruler");

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>483</width>
<height>341</height>
<height>361</height>
</rect>
</property>
<property name="windowTitle">
@ -59,6 +59,23 @@
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Far style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="2" colspan="2">
<widget class="QCheckBox" name="show_ruler">
<property name="text">
<string>Show ruler</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QComboBox" name="style1_cbx">
<item>
@ -108,7 +125,122 @@
</item>
</widget>
</item>
<item row="10" column="1">
<item row="2" column="4">
<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>
<item row="0" column="3">
<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>
<item row="1" column="0" colspan="5">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QPushButton" name="grid_axis_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Grid </string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="5">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="grid_net_color_pb">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Ruler</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QPushButton" name="grid_ruler_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Axis</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="grid_grid_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="Close style">
<property name="text">
<string>Close style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color (all)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Color</string>
@ -118,14 +250,17 @@
</property>
</widget>
</item>
<item row="5" column="0" colspan="5">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="7" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2" colspan="2">
<item row="7" column="2" colspan="2">
<widget class="QComboBox" name="style0_cbx">
<item>
<property name="text">
@ -169,30 +304,23 @@
</item>
</widget>
</item>
<item row="0" column="3">
<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>
<item row="10" column="2">
<widget class="QPushButton" name="grid_ruler_color_pb">
<item row="8" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string/>
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="4" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -245,141 +373,37 @@
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Far style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="Close style">
<property name="text">
<string>Close style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color (all)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="grid_grid_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Grid </string>
</property>
</widget>
</item>
<item row="9" column="2" colspan="2">
<widget class="QCheckBox" name="show_ruler">
<property name="text">
<string>Show Ruler</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QPushButton" name="grid_axis_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="4">
<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>
<item row="6" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="grid_net_color_pb">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Axis</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Ruler</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="5">
<item row="9" column="0" colspan="5">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="grid_density_sb">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Min. spacing</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="3" colspan="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>(Font height units)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -41,6 +41,8 @@ namespace lay
// ------------------------------------------------------------
// Helper functions to get and set the configuration
int default_density = 4;
static struct {
lay::GridNet::GridStyle style;
const char *string;
@ -79,6 +81,20 @@ GridNetStyleConverter::to_string (lay::GridNet::GridStyle style)
return "";
}
void
GridNetDensityConverter::from_string (const std::string &value, int &density)
{
density = default_density; // original default
tl::Extractor ex (value.c_str ());
ex.try_read (density);
}
std::string
GridNetDensityConverter::to_string (int density)
{
return tl::to_string (density);
}
// ------------------------------------------------------------
// Implementation of the GridNetPluginDeclaration
@ -92,6 +108,7 @@ GridNetPluginDeclaration::get_options (std::vector < std::pair<std::string, std:
options.push_back (std::pair<std::string, std::string> (cfg_grid_style0, GridNetStyleConverter ().to_string (lay::GridNet::Invisible)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_style1, GridNetStyleConverter ().to_string (lay::GridNet::Dots)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_style2, GridNetStyleConverter ().to_string (lay::GridNet::TenthDottedLines)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_density, ""));
options.push_back (std::pair<std::string, std::string> (cfg_grid_visible, tl::to_string (true)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_show_ruler, tl::to_string (true)));
// grid-micron is not configured here since some other entity is supposed to do this.
@ -122,7 +139,8 @@ GridNet::GridNet (LayoutViewBase *view)
lay::Plugin (view),
mp_view (view),
m_visible (false), m_show_ruler (true), m_grid (1.0),
m_style0 (Invisible), m_style1 (Invisible), m_style2 (Invisible)
m_style0 (Invisible), m_style1 (Invisible), m_style2 (Invisible),
m_density (default_density)
{
// .. nothing yet ..
}
@ -175,6 +193,12 @@ GridNet::configure (const std::string &name, const std::string &value)
GridNetStyleConverter ().from_string (value, style);
need_update = test_and_set (m_style2, style);
} else if (name == cfg_grid_density) {
int density = 0;
GridNetDensityConverter ().from_string (value, density);
need_update = test_and_set (m_density, density);
} else if (name == cfg_grid_show_ruler) {
bool sr = false;
@ -246,13 +270,14 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
// fw is the basic unit of the ruler geometry
int fwr = lay::FixedFont::get_font (bmp_canvas->font_resolution ()).width ();
int threshold = std::min (1000, m_density * fwr);
double dgrid = trans.ctrans (m_grid);
GridStyle style = m_style1;
// compute major grid and switch to secondary style if necessary
int s = 0;
while (dgrid < fwr * 4) {
while (dgrid < threshold) {
if (s == 0) {
dgrid *= 2.0;
} else if (s == 1) {
@ -279,56 +304,6 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
int nx = int (dbworld.width () / grid + eps) + 2;
int ny = int (dbworld.height () / grid + eps) + 2;
if (m_show_ruler && dgrid < vp.width () * 0.2) {
int rh = int (floor (0.5 + fwr * 0.8));
int xoffset = int (floor (0.5 + fwr * 2.5));
int yoffset = int (floor (0.5 + fwr * 2.5));
painter.fill_rect (db::Point (xoffset, vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_rect (db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + 2 * dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_text (tl::sprintf ("%g \265m", grid * 2).c_str (),
db::Point (xoffset + int (floor (0.5 + trans.ctrans (2 * grid))), vp.height () - yoffset - rh / 2 - 2),
ruler_color, -1, 1);
if (mp_view->global_trans ().fp_trans () != db::DFTrans ()) {
// draw a small "F" indicating any global transformation
db::Point pts[] = {
db::Point (-4, -5),
db::Point (-4, 5),
db::Point (4, 5),
db::Point (4, 3),
db::Point (-2, 3),
db::Point (-2, 1),
db::Point (3, 1),
db::Point (3, -1),
db::Point (-2, -1),
db::Point (-2, -5),
db::Point (-4, -5)
};
db::Polygon poly;
poly.assign_hull (&pts[0], &pts[0] + (sizeof (pts) / sizeof (pts[0])));
poly.transform (db::FTrans (mp_view->global_trans ().fp_trans ()));
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); !e.at_end (); ++e) {
db::Point p0 (xoffset + 2 * rh, vp.height () - yoffset - rh * 5);
db::Point p1 = p0 + db::Vector (int (floor (0.5 + (*e).p1 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p1 ().y () * 0.1 * rh * 4)));
db::Point p2 = p0 + db::Vector (int (floor (0.5 + (*e).p2 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p2 ().y () * 0.1 * rh * 4)));
painter.draw_line (p1, p2, ruler_color);
}
}
}
// draw grid
if (style == Dots || style == TenthDottedLines ||
style == DottedLines || style == LightDottedLines) {
@ -549,6 +524,56 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
}
if (m_show_ruler && dgrid < vp.width () * 0.4) {
int rh = int (floor (0.5 + fwr * 0.8));
int xoffset = int (floor (0.5 + fwr * 2.5));
int yoffset = int (floor (0.5 + fwr * 2.5));
painter.fill_rect (db::Point (xoffset, vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_rect (db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + 2 * dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_text (tl::sprintf ("%g \265m", grid * 2).c_str (),
db::Point (xoffset + int (floor (0.5 + trans.ctrans (2 * grid))), vp.height () - yoffset - rh / 2 - 2),
ruler_color, -1, 1);
if (mp_view->global_trans ().fp_trans () != db::DFTrans ()) {
// draw a small "F" indicating any global transformation
db::Point pts[] = {
db::Point (-4, -5),
db::Point (-4, 5),
db::Point (4, 5),
db::Point (4, 3),
db::Point (-2, 3),
db::Point (-2, 1),
db::Point (3, 1),
db::Point (3, -1),
db::Point (-2, -1),
db::Point (-2, -5),
db::Point (-4, -5)
};
db::Polygon poly;
poly.assign_hull (&pts[0], &pts[0] + (sizeof (pts) / sizeof (pts[0])));
poly.transform (db::FTrans (mp_view->global_trans ().fp_trans ()));
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); !e.at_end (); ++e) {
db::Point p0 (xoffset + 2 * rh, vp.height () - yoffset - rh * 5);
db::Point p1 = p0 + db::Vector (int (floor (0.5 + (*e).p1 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p1 ().y () * 0.1 * rh * 4)));
db::Point p2 = p0 + db::Vector (int (floor (0.5 + (*e).p2 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p2 ().y () * 0.1 * rh * 4)));
painter.draw_line (p1, p2, ruler_color);
}
}
}
}
}

View File

@ -87,6 +87,7 @@ private:
GridStyle m_style0;
GridStyle m_style1;
GridStyle m_style2;
int m_density;
};
class GridNetStyleConverter
@ -96,6 +97,13 @@ public:
std::string to_string (lay::GridNet::GridStyle style);
};
class GridNetDensityConverter
{
public:
void from_string (const std::string &value, int &density);
std::string to_string (int density);
};
}
#endif

View File

@ -94,6 +94,10 @@ GridNetConfigPage::setup (lay::Dispatcher *root)
style = lay::GridNet::Invisible;
root->config_get (cfg_grid_style2, style, GridNetStyleConverter ());
mp_ui->style2_cbx->setCurrentIndex (int (style));
int density = 0;
root->config_get (cfg_grid_density, density, GridNetDensityConverter ());
mp_ui->grid_density_sb->setValue (density);
}
void
@ -108,6 +112,7 @@ GridNetConfigPage::commit (lay::Dispatcher *root)
root->config_set (cfg_grid_style0, lay::GridNet::GridStyle (mp_ui->style0_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_style1, lay::GridNet::GridStyle (mp_ui->style1_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_style2, lay::GridNet::GridStyle (mp_ui->style2_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_density, mp_ui->grid_density_sb->value (), GridNetDensityConverter ());
}
} // namespace lay

View File

@ -661,15 +661,15 @@ D25ViewWidget::enter (const db::RecursiveShapeIterator *iter, double zstart, dou
void
D25ViewWidget::entry (const db::Region &data, double dbu, double zstart, double zstop)
{
// try to establish a default color from the region's origin if required
const db::RecursiveShapeIterator *iter = 0;
const db::OriginalLayerRegion *original = dynamic_cast<const db::OriginalLayerRegion *> (data.delegate ());
if (original) {
iter = original->iter ();
// try to establish a default color from the region's origin if required
auto it = original->begin_iter ();
enter (&it.first, zstart, zstop);
} else {
enter (0, zstart, zstop);
}
enter (iter, zstart, zstop);
tl::AbsoluteProgress progress (tl::to_string (tr ("Rendering ...")));
render_region (progress, *m_layers.back ().vertex_chunk, *m_layers.back ().normals_chunk, *m_layers.back ().line_chunk, data, dbu, db::CplxTrans (dbu).inverted () * m_bbox, zstart, zstop);
}
@ -677,15 +677,15 @@ D25ViewWidget::entry (const db::Region &data, double dbu, double zstart, double
void
D25ViewWidget::entry (const db::Edges &data, double dbu, double zstart, double zstop)
{
// try to establish a default color from the region's origin if required
const db::RecursiveShapeIterator *iter = 0;
const db::OriginalLayerEdges *original = dynamic_cast<const db::OriginalLayerEdges *> (data.delegate ());
if (original) {
iter = original->iter ();
// try to establish a default color from the region's origin if required
auto it = original->begin_iter ();
enter (&it.first, zstart, zstop);
} else {
enter (0, zstart, zstop);
}
enter (iter, zstart, zstop);
tl::AbsoluteProgress progress (tl::to_string (tr ("Rendering ...")));
render_edges (progress, *m_layers.back ().vertex_chunk, *m_layers.back ().normals_chunk, *m_layers.back ().line_chunk, data, dbu, db::CplxTrans (dbu).inverted () * m_bbox, zstart, zstop);
}
@ -693,15 +693,15 @@ D25ViewWidget::entry (const db::Edges &data, double dbu, double zstart, double z
void
D25ViewWidget::entry (const db::EdgePairs &data, double dbu, double zstart, double zstop)
{
// try to establish a default color from the region's origin if required
const db::RecursiveShapeIterator *iter = 0;
const db::OriginalLayerEdgePairs *original = dynamic_cast<const db::OriginalLayerEdgePairs *> (data.delegate ());
if (original) {
iter = original->iter ();
// try to establish a default color from the region's origin if required
auto it = original->begin_iter ();
enter (&it.first, zstart, zstop);
} else {
enter (0, zstart, zstop);
}
enter (iter, zstart, zstop);
tl::AbsoluteProgress progress (tl::to_string (tr ("Rendering ...")));
render_edge_pairs (progress, *m_layers.back ().vertex_chunk, *m_layers.back ().normals_chunk, *m_layers.back ().line_chunk, data, dbu, db::CplxTrans (dbu).inverted () * m_bbox, zstart, zstop);
}

26
testdata/drc/drcSimpleTests_94.drc vendored Normal file
View File

@ -0,0 +1,26 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l1.output(1, 0)
l2.output(2, 0)
x = l1 ^ l2
# we detect point-like polygons here by explicitly
# iterating. The enlargement makes sure, we have something
# to write to the output layout.
boxes = x.data.each.collect do |p|
RBA::Box::new(p.bbox.enlarged(10, 10))
end
x.data = RBA::Region::new(boxes)
x.output(10, 0)

BIN
testdata/drc/drcSimpleTests_94.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au94.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au94d.gds vendored Normal file

Binary file not shown.