mirror of https://github.com/KLayout/klayout.git
Added text support in DRC
- A new constructor for RBA::Region has been provided to create text markers from a shape iterator - The DRC framework has been enhanced with a "text" function
This commit is contained in:
parent
801f83f09c
commit
8396463daf
|
|
@ -1493,6 +1493,16 @@ public:
|
|||
return db::RecursiveShapeIterator (m_iter).at_end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the internal iterator
|
||||
*
|
||||
* This method is intended for users who know what they are doing
|
||||
*/
|
||||
const db::RecursiveShapeIterator &iter () const
|
||||
{
|
||||
return m_iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ensures the region has valid polygons
|
||||
*
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
#include "dbPolygonTools.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbShapes.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
|
@ -69,6 +72,43 @@ static db::Region *new_shapes (const db::Shapes &s)
|
|||
return r;
|
||||
}
|
||||
|
||||
static db::Region *new_si_texts (const db::RecursiveShapeIterator &si_in, const std::string &pat, bool pattern)
|
||||
{
|
||||
db::RecursiveShapeIterator si (si_in);
|
||||
si.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
tl::GlobPattern glob_pat;
|
||||
bool all = false;
|
||||
if (pattern) {
|
||||
if (pat == "*") {
|
||||
all = true;
|
||||
} else {
|
||||
glob_pat = tl::GlobPattern (pat);
|
||||
}
|
||||
}
|
||||
|
||||
std::auto_ptr<db::Region> r (new db::Region ());
|
||||
|
||||
while (! si.at_end ()) {
|
||||
if (si.shape ().is_text () &&
|
||||
(all || (pattern && glob_pat.match (si.shape ().text_string ())) || (!pattern && si.shape ().text_string () == pat))) {
|
||||
db::Text t;
|
||||
si.shape ().text (t);
|
||||
t.transform (si.trans ());
|
||||
r->insert (db::Box (t.box ().enlarged (db::Vector (1, 1))));
|
||||
}
|
||||
si.next ();
|
||||
}
|
||||
|
||||
return r.release ();
|
||||
}
|
||||
|
||||
static db::Region texts (const db::Region *r, const std::string &pat, bool pattern)
|
||||
{
|
||||
std::auto_ptr<db::Region> o (new_si_texts (r->iter (), pat, pattern));
|
||||
return *o;
|
||||
}
|
||||
|
||||
static db::Region *new_si (const db::RecursiveShapeIterator &si)
|
||||
{
|
||||
return new db::Region (si);
|
||||
|
|
@ -595,6 +635,30 @@ Class<db::Region> decl_Region ("Region",
|
|||
"r = RBA::Region::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
constructor ("new", &new_si_texts, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
|
||||
"@brief Constructor from a text set\n"
|
||||
"\n"
|
||||
"@param shape_iterator The iterator from which to derive the texts\n"
|
||||
"@param expr The selection string\n"
|
||||
"@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n"
|
||||
"\n"
|
||||
"This special constructor will create a region from the text objects delivered by the shape iterator. "
|
||||
"Each text object will deliver a small (non-empty) box that represents the text origin.\n"
|
||||
"Texts can be selected by their strings - either through a glob pattern or by exact comparison with "
|
||||
"the given string. The following options are available:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"region = RBA::Region::new(iter, \"*\") # all texts\n"
|
||||
"region = RBA::Region::new(iter, \"A*\") # all texts starting with an 'A'\n"
|
||||
"region = RBA::Region::new(iter, \"A*\", false) # all texts exactly matchin 'A*'\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
method_ext ("texts", &texts, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
method ("merged_semantics=", &db::Region::set_merged_semantics,
|
||||
"@brief Enables or disables merged semantics\n"
|
||||
"@args f\n"
|
||||
|
|
|
|||
|
|
@ -801,6 +801,35 @@ CODE
|
|||
DRCLayer::new(@engine, @engine._tcmd(@data, 0, RBA::Region, :smoothed, prep_value(d)))
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name texts
|
||||
# @brief Selects texts from an original layer
|
||||
# @synopsis layer.texts
|
||||
# @synopsis layer.texts(text)
|
||||
# @synopsis layer.texts(text, true)
|
||||
# @synopsis layer.texts(text, false)
|
||||
# This method can be applied to original layers - i.e. ones that have
|
||||
# been created with \input. It will produce a small box (2x2 DBU) on each
|
||||
# selected texts.
|
||||
#
|
||||
# Texts can be selected either by exact match or pattern match with a
|
||||
# glob-style pattern. The second argument selects pattern style (true)
|
||||
# or exact match (false).
|
||||
#
|
||||
# @code
|
||||
# # Selects all texts
|
||||
# t = input(1, 0).texts
|
||||
# # Selects all texts beginning with an "A"
|
||||
# t = input(1, 0).texts("A*")
|
||||
# t = input(1, 0).texts("A*", true)
|
||||
# # Selects all texts whose string is "A*"
|
||||
# t = input(1, 0).texts("A*", false)
|
||||
# @/code
|
||||
|
||||
def texts(expr = "*", as_pattern = true)
|
||||
DRCLayer::new(@engine, @engine._tcmd(@data, 0, RBA::Region, :texts, expr, as_pattern))
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name odd_polygons
|
||||
# @brief Checks for odd polygons (self-overlapping, non-orientable)
|
||||
|
|
|
|||
|
|
@ -497,6 +497,9 @@ cell("TOP")
|
|||
|
||||
c1.rounded_corners(0.5, 0.5, 16).output(1010, 0)
|
||||
c1.smoothed(1.5).output(1011, 0)
|
||||
a1.texts.output(1020, 0)
|
||||
a1.texts("A*").output(1021, 0)
|
||||
a1.texts("A*", false).output(1022, 0)
|
||||
|
||||
puts "=== Single-cell testsuite ==="
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -115,12 +115,15 @@ class DBRegion_TestClass < TestBase
|
|||
|
||||
ly = RBA::Layout::new
|
||||
l1 = ly.layer("l1")
|
||||
l2 = ly.layer("l2")
|
||||
c1 = ly.create_cell("C1")
|
||||
c2 = ly.create_cell("C2")
|
||||
c1.insert(RBA::CellInstArray::new(c2.cell_index, RBA::Trans::new(0, 0)))
|
||||
c1.insert(RBA::CellInstArray::new(c2.cell_index, RBA::Trans::new(0, 100)))
|
||||
c1.insert(RBA::CellInstArray::new(c2.cell_index, RBA::Trans::new(200, 100)))
|
||||
c2.shapes(l1).insert(RBA::Box::new(-10, -20, 10, 20))
|
||||
c2.shapes(l2).insert(RBA::Text::new("AA", RBA::Vector::new(-10, -20)))
|
||||
c2.shapes(l2).insert(RBA::Text::new("BB", RBA::Vector::new(10, 20)))
|
||||
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l1))
|
||||
assert_equal(r.to_s, "(-10,-20;-10,20;10,20;10,-20);(-10,80;-10,120;10,120;10,80);(190,80;190,120;210,120;210,80)")
|
||||
|
|
@ -131,6 +134,15 @@ class DBRegion_TestClass < TestBase
|
|||
assert_equal(r.bbox.to_s, "(-10,-20;210,120)")
|
||||
assert_equal(r.is_merged?, false)
|
||||
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "*")
|
||||
assert_equal(r.to_s, "(-11,-21;-11,-19;-9,-19;-9,-21);(9,19;9,21;11,21;11,19);(-11,79;-11,81;-9,81;-9,79);(9,119;9,121;11,121;11,119);(189,79;189,81;191,81;191,79);(209,119;209,121;211,121;211,119)")
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "A*")
|
||||
assert_equal(r.to_s, "(-11,-21;-11,-19;-9,-19;-9,-21);(-11,79;-11,81;-9,81;-9,79);(189,79;189,81;191,81;191,79)")
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "A*", false)
|
||||
assert_equal(r.to_s, "")
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "AA", false)
|
||||
assert_equal(r.to_s, "(-11,-21;-11,-19;-9,-19;-9,-21);(-11,79;-11,81;-9,81;-9,79);(189,79;189,81;191,81;191,79)")
|
||||
|
||||
r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l1), RBA::ICplxTrans::new(10, 20))
|
||||
assert_equal(r.to_s, "(0,0;0,40;20,40;20,0);(0,100;0,140;20,140;20,100);(200,100;200,140;220,140;220,100)")
|
||||
assert_equal(r.extents.to_s, "(0,0;0,40;20,40;20,0);(0,100;0,140;20,140;20,100);(200,100;200,140;220,140;220,100)")
|
||||
|
|
|
|||
Loading…
Reference in New Issue