mirror of https://github.com/KLayout/klayout.git
z Stack description language enhanced.
This commit is contained in:
parent
25b978f39f
commit
773fcb6b67
|
|
@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
// provide some explanation for the initialization
|
||||
m_src =
|
||||
"# Provide z stack information here\n"
|
||||
"#\n"
|
||||
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n"
|
||||
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
|
||||
"# Named arguments are:\n"
|
||||
|
|
@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
"# zstop The upper z position of the extruded layer in µm\n"
|
||||
"# height The height of the extruded layer in µm\n"
|
||||
"#\n"
|
||||
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', "
|
||||
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',\n"
|
||||
"# the upper level of the previous layer will be used.\n"
|
||||
"#\n"
|
||||
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n"
|
||||
|
|
@ -139,6 +140,30 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
"# 1: zstop=1.5, zstart=0.5 # same with named parameters\n"
|
||||
"# 1: height=1.0, zstop=1.5 # same with z stop minus height\n"
|
||||
"# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
|
||||
"#\n"
|
||||
"# VARIABLES\n"
|
||||
"#\n"
|
||||
"# You can declare variables with:\n"
|
||||
"# var name = value\n"
|
||||
"#\n"
|
||||
"# You can use variables inside numeric expressions.\n"
|
||||
"# Example:\n"
|
||||
"# var hmetal = 0.48\n"
|
||||
"# 7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n"
|
||||
"#\n"
|
||||
"# You cannot use variables inside layer specifications currently.\n"
|
||||
"#\n"
|
||||
"# CONDITIONALS\n"
|
||||
"#\n"
|
||||
"# You can enable or disable branches of the table using 'if', 'else', 'elseif' and 'end':\n"
|
||||
"# Example:\n"
|
||||
"# var thick_m1 = true\n"
|
||||
"# if thickm1\n"
|
||||
"# 1: 0.5 1.5\n"
|
||||
"# else\n"
|
||||
"# 1: 0.5 1.2\n"
|
||||
"# end\n"
|
||||
"\n"
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +182,9 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
|
||||
try {
|
||||
|
||||
tl::Eval eval;
|
||||
std::vector<bool> conditional_stack;
|
||||
|
||||
std::vector<std::string> lines = tl::split (src, "\n");
|
||||
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
|
||||
|
||||
|
|
@ -168,6 +196,64 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
// ignore comments
|
||||
} else if (ex.at_end ()) {
|
||||
// ignore empty lines
|
||||
|
||||
} else if (ex.test ("if")) {
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
conditional_stack.push_back (x.execute ().to_bool ());
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("else")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'else' without 'if'")));
|
||||
}
|
||||
|
||||
conditional_stack.back () = ! conditional_stack.back ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("end")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'end' without 'if'")));
|
||||
}
|
||||
|
||||
conditional_stack.pop_back ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("elsif")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'elsif' without 'if'")));
|
||||
}
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
conditional_stack.back () = x.execute ().to_bool ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (! conditional_stack.empty () && ! conditional_stack.back ()) {
|
||||
|
||||
continue;
|
||||
|
||||
} else if (ex.test ("var")) {
|
||||
|
||||
std::string n;
|
||||
ex.read_name (n);
|
||||
|
||||
ex.expect ("=");
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
eval.set_var (n, x.execute ());
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else {
|
||||
|
||||
db::D25LayerInfo info;
|
||||
|
|
@ -191,16 +277,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
break;
|
||||
}
|
||||
|
||||
double pv = 0.0;
|
||||
tl::Expression pvx;
|
||||
|
||||
std::string pn;
|
||||
if (ex.try_read_name (pn)) {
|
||||
ex.expect ("=");
|
||||
ex.read (pv);
|
||||
eval.parse (pvx, ex);
|
||||
} else {
|
||||
ex.read (pv);
|
||||
eval.parse (pvx, ex);
|
||||
}
|
||||
|
||||
double pv = pvx.execute ().to_double ();
|
||||
|
||||
ex.test (",");
|
||||
|
||||
if (pn.empty ()) {
|
||||
|
|
@ -239,28 +327,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
} else if (args.size () == 1) {
|
||||
if (! h.is_nil ()) {
|
||||
if (! z0.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
|
||||
}
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
|
||||
}
|
||||
info.set_zstart (args[0]);
|
||||
info.set_zstop (args[0] + h.to_double ());
|
||||
} else {
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
|
||||
}
|
||||
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
|
||||
}
|
||||
} else if (args.size () == 2) {
|
||||
if (! z0.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
|
||||
}
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop already given")));
|
||||
}
|
||||
if (! h.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: height implicitly given")));
|
||||
}
|
||||
info.set_zstart (args[0]);
|
||||
info.set_zstop (args[1]);
|
||||
|
|
@ -268,12 +356,14 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)")));
|
||||
}
|
||||
|
||||
m_layers.push_back (info);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'if', 'else' or 'elsif' without matching 'end'")));
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@
|
|||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
|||
|
|
@ -5,13 +5,33 @@
|
|||
|
||||
<highlighting>
|
||||
|
||||
<list name="Control Keywords">
|
||||
<item> zstart </item>
|
||||
<item> zstop </item>
|
||||
<item> height </item>
|
||||
</list>
|
||||
|
||||
<list name="Expression Keywords">
|
||||
<item> true </item>
|
||||
<item> false </item>
|
||||
<item> nil </item>
|
||||
</list>
|
||||
|
||||
<contexts>
|
||||
|
||||
<context name="Normal" attribute="Normal Text">
|
||||
<context name="Normal" attribute="Normal Text" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
|
||||
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
|
||||
<StringDetect attribute="Symbol" String="var" context="Expect Assignment"/>
|
||||
<StringDetect attribute="Symbol" String="if" context="Expression"/>
|
||||
<StringDetect attribute="Symbol" String="elsif" context="Expression"/>
|
||||
<StringDetect attribute="Symbol" String="else" context="Expect Lineend"/>
|
||||
<StringDetect attribute="Symbol" String="end" context="Expect Lineend"/>
|
||||
|
||||
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
||||
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
|
||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
|
||||
|
||||
<RegExpr attribute="Normal" String=":" context="After LD"/>
|
||||
|
||||
|
|
@ -22,22 +42,52 @@
|
|||
<DetectChar attribute="Normal" char="/" context="#stay"/>
|
||||
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
|
||||
|
||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
||||
|
||||
</context>
|
||||
|
||||
<context name="Comment" attribute="Comment" lineEndContext="Normal">
|
||||
</context>
|
||||
|
||||
<context name="After LD" attribute="Normal" lineEndContext="Normal">
|
||||
<context name="Expect Lineend" attribute="Normal" lineEndContext="Normal" fallthrough="true" fallthroughContext="Error">
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||
</context>
|
||||
|
||||
<context name="Expression" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
|
||||
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||
|
||||
<keyword attribute="Symbol" String="Expression Keywords" context="#stay"/>
|
||||
<keyword attribute="Symbol" String="Control Keywords" context="Expect Expression"/>
|
||||
|
||||
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
||||
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
|
||||
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="#stay"/>
|
||||
<RegExpr attribute="Float" String="\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="#stay"/>
|
||||
|
||||
<DetectChar attribute="Normal" char="," context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="=" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="zstart" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="zstop" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="height" context="#stay"/>
|
||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
||||
<DetectChar attribute="Normal" char="(" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char=")" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="[" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="]" context="#stay"/>
|
||||
|
||||
<RegExpr attribute="Normal" String="[\^\*\.\+\-%/!=<>&|,\?:]" context="#stay"/>
|
||||
|
||||
</context>
|
||||
|
||||
<context name="Expect Expression" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="=" context="Expression"/>
|
||||
</context>
|
||||
|
||||
<context name="Expect Assignment" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="Expect Expression"/>
|
||||
</context>
|
||||
|
||||
<context name="After LD" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Expression">
|
||||
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||
<DetectChar attribute="Comment" char="#" context="Error"/>
|
||||
</context>
|
||||
|
||||
<context name="Error" attribute="Error" lineEndContext="Normal">
|
||||
|
|
@ -46,19 +96,21 @@
|
|||
<context name="Quoted String" attribute="String" lineEndContext="Error">
|
||||
<StringDetect attribute="String" String="\\" context="#stay"/>
|
||||
<RegExpr attribute="String" String="\\\"" context="#stay"/>
|
||||
<DetectChar char=""" attribute="String" context="Normal"/>
|
||||
<DetectChar char=""" attribute="String" context="#pop"/>
|
||||
</context>
|
||||
|
||||
<context name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
|
||||
<StringDetect attribute="String" String="\\" context="#stay"/>
|
||||
<RegExpr attribute="String" String="\\\'" context="#stay"/>
|
||||
<DetectChar char="'" attribute="Raw String" context="Normal"/>
|
||||
<DetectChar char="'" attribute="Raw String" context="#pop"/>
|
||||
</context>
|
||||
|
||||
</contexts>
|
||||
|
||||
<itemDatas>
|
||||
|
||||
<itemData name="Normal Text" defStyleNum="dsNormal"/>
|
||||
<itemData name="Name" defStyleNum="dsNormal"/>
|
||||
|
||||
<itemData name="Comment" defStyleNum="dsComment"/>
|
||||
<itemData name="Float" defStyleNum="dsFloat"/>
|
||||
|
|
@ -73,4 +125,12 @@
|
|||
</itemDatas>
|
||||
|
||||
</highlighting>
|
||||
|
||||
<general>
|
||||
<comments>
|
||||
<comment name="singleLine" start="#"/>
|
||||
</comments>
|
||||
<keywords casesensitive="1" weakDeliminator="!?"/>
|
||||
</general>
|
||||
|
||||
</language>
|
||||
|
|
|
|||
|
|
@ -246,40 +246,23 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
|||
|
||||
} else {
|
||||
|
||||
// compute vector of line of sight
|
||||
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
||||
|
||||
// by definition the ray goes through the camera position
|
||||
QVector3D hp = hit_point_with_scene (ray.second);
|
||||
double d = event->angleDelta ().y () * (1.0 / (90 * 16));
|
||||
|
||||
if (! (event->modifiers () & Qt::ControlModifier)) {
|
||||
|
||||
// No Ctrl is closeup
|
||||
// No Ctrl is "move horizontally along the azimuth axis"
|
||||
|
||||
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
|
||||
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
|
||||
QMatrix4x4 t;
|
||||
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||
QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ()));
|
||||
|
||||
m_displacement += (d / m_scale_factor) * cd;
|
||||
|
||||
} else {
|
||||
|
||||
// "Ctrl" is zoom
|
||||
|
||||
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
||||
|
||||
QVector3D initial_displacement = m_displacement;
|
||||
QVector3D displacement = m_displacement;
|
||||
|
||||
m_scale_factor *= f;
|
||||
displacement += hp * (1.0 - f) / m_scale_factor;
|
||||
|
||||
// normalize the scene translation so the scene does not "flee"
|
||||
|
||||
QMatrix4x4 ct = cam_trans ();
|
||||
initial_displacement = ct.map (initial_displacement);
|
||||
displacement = ct.map (displacement);
|
||||
|
||||
lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ());
|
||||
|
||||
m_displacement = ct.inverted ().map (displacement);
|
||||
m_scale_factor *= exp (d);
|
||||
|
||||
emit scale_factor_changed (m_scale_factor);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue