mirror of https://github.com/KLayout/klayout.git
commit
974756536f
|
|
@ -1052,6 +1052,10 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const
|
|||
|
||||
return AsIfFlatEdges::and_with (other);
|
||||
|
||||
} else if (deep_layer () == other_deep->deep_layer ()) {
|
||||
|
||||
return clone ();
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepEdges (and_or_not_with (other_deep, EdgeAnd).first);
|
||||
|
|
@ -1071,6 +1075,10 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const
|
|||
|
||||
return AsIfFlatEdges::not_with (other);
|
||||
|
||||
} else if (deep_layer () == other_deep->deep_layer ()) {
|
||||
|
||||
return new DeepEdges (deep_layer ().derived ());
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepEdges (and_or_not_with (other_deep, EdgeNot).first);
|
||||
|
|
@ -1164,6 +1172,10 @@ DeepEdges::andnot_with (const Edges &other) const
|
|||
|
||||
return AsIfFlatEdges::andnot_with (other);
|
||||
|
||||
} else if (deep_layer () == other_deep->deep_layer ()) {
|
||||
|
||||
return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));
|
||||
|
||||
} else {
|
||||
|
||||
auto res = and_or_not_with (other_deep, EdgeAndNot);
|
||||
|
|
@ -1188,6 +1200,10 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
|
|||
|
||||
return AsIfFlatEdges::xor_with (other);
|
||||
|
||||
} else if (deep_layer () == other_deep->deep_layer ()) {
|
||||
|
||||
return new DeepEdges (deep_layer ().derived ());
|
||||
|
||||
} else {
|
||||
|
||||
// Implement XOR as (A-B)+(B-A) - only this implementation
|
||||
|
|
@ -1203,6 +1219,11 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
|
|||
|
||||
EdgesDelegate *DeepEdges::or_with (const Edges &other) const
|
||||
{
|
||||
const DeepEdges *other_deep = dynamic_cast <const DeepEdges *> (other.delegate ());
|
||||
if (other_deep && other_deep->deep_layer () == deep_layer ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
// NOTE: in the hierarchical case we don't do a merge on "or": just map to add
|
||||
return add (other);
|
||||
}
|
||||
|
|
@ -1503,8 +1524,19 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer () && !counting) {
|
||||
if ((mode == EdgesOutside) == inverse) {
|
||||
return clone ();
|
||||
} else {
|
||||
return new DeepEdges (deep_layer ().derived ());
|
||||
}
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
||||
db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal, min_count, max_count);
|
||||
|
|
@ -1513,8 +1545,13 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
|
|||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ());
|
||||
if (edges == other_edges) {
|
||||
// with counting and two identical inputs, a copy needs to be made
|
||||
db::DeepLayer copy (other_edges.copy ());
|
||||
proc.run (&op, edges.layer (), copy.layer (), dl_out.layer ());
|
||||
} else {
|
||||
proc.run (&op, edges.layer (), other_edges.layer (), dl_out.layer ());
|
||||
}
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
|
@ -1533,8 +1570,19 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer () && !counting) {
|
||||
if (mode != EdgesOutside) {
|
||||
return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));
|
||||
} else {
|
||||
return std::make_pair (new DeepEdges (deep_layer ().derived ()), clone ());
|
||||
}
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
DeepLayer dl_out2 (edges.derived ());
|
||||
|
||||
|
|
@ -1550,7 +1598,13 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
|
|||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers);
|
||||
if (edges == other_edges) {
|
||||
// with counting and two identical inputs, a copy needs to be made
|
||||
db::DeepLayer copy (other_edges.copy ());
|
||||
proc.run (&op, edges.layer (), copy.layer (), output_layers);
|
||||
} else {
|
||||
proc.run (&op, edges.layer (), other_edges.layer (), output_layers);
|
||||
}
|
||||
|
||||
return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2));
|
||||
}
|
||||
|
|
@ -1591,6 +1645,10 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = deep_layer ();
|
||||
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();
|
||||
|
||||
|
|
@ -1617,6 +1675,10 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer ()) {
|
||||
return invert ? new db::DeepEdges (deep_layer ().derived ()) : clone ();
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
|
@ -1646,6 +1708,10 @@ std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (const Edges &
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer ()) {
|
||||
return std::make_pair (clone (), new db::DeepEdges (deep_layer ().derived ()));
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
|
|
|||
|
|
@ -797,6 +797,10 @@ DeepRegion::and_with (const Region &other, PropertyConstraint property_constrain
|
|||
|
||||
return AsIfFlatRegion::and_with (other, property_constraint);
|
||||
|
||||
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
|
||||
|
||||
return clone ();
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
|
||||
|
|
@ -817,6 +821,10 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
|
|||
|
||||
return AsIfFlatRegion::not_with (other, property_constraint);
|
||||
|
||||
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
|
||||
|
||||
return new DeepRegion (deep_layer ().derived ());
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
|
||||
|
|
@ -825,8 +833,13 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
|
||||
DeepRegion::or_with (const Region &other, db::PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
if (other_deep && other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
// TODO: implement property_constraint
|
||||
RegionDelegate *res = add (other);
|
||||
return res->merged_in_place ();
|
||||
|
|
@ -849,6 +862,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr
|
|||
|
||||
return AsIfFlatRegion::andnot_with (other, property_constraint);
|
||||
|
||||
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
|
||||
|
||||
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep, property_constraint);
|
||||
|
|
@ -962,6 +979,10 @@ DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_const
|
|||
|
||||
return AsIfFlatRegion::xor_with (other, property_constraint);
|
||||
|
||||
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
|
||||
|
||||
return new DeepRegion (deep_layer ().derived ());
|
||||
|
||||
} else {
|
||||
|
||||
// Implement XOR as (A-B)+(B-A) - only this implementation
|
||||
|
|
@ -2127,6 +2148,16 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer ()) {
|
||||
if (output_mode == PositiveAndNegative) {
|
||||
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
}
|
||||
}
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
|
||||
|
||||
|
|
@ -2188,6 +2219,26 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer () && !counting) {
|
||||
if (mode <= 0 /*inside or interacting*/) {
|
||||
if (output_mode == PositiveAndNegative) {
|
||||
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
}
|
||||
} else {
|
||||
if (output_mode == PositiveAndNegative) {
|
||||
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
// NOTE: with counting, the other polygons must be merged
|
||||
const db::DeepLayer &other_polygons = counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
|
||||
|
|
@ -2205,7 +2256,13 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
|
||||
if (polygons == other_polygons) {
|
||||
// with counting and two identical inputs we need to create a layer copy
|
||||
db::DeepLayer other_copy (other_polygons.copy ());
|
||||
proc.run (&op, polygons.layer (), other_copy.layer (), orh.layers ());
|
||||
} else {
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
|
||||
}
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
|
@ -2285,6 +2342,10 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
if (deep_layer () == other_deep->deep_layer ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
// in "inside" mode, the first argument needs to be merged too
|
||||
const db::DeepLayer &polygons = mode < 0 ? merged_deep_layer () : deep_layer ();
|
||||
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
|
||||
|
|
|
|||
|
|
@ -1505,6 +1505,55 @@ TEST(22_InteractingWithCount)
|
|||
EXPECT_EQ (db::compare (e.selected_interacting_differential (r2, size_t (2), size_t(3)).second, "(0,0;200,0)"), true);
|
||||
}
|
||||
|
||||
TEST(23_SameInputs)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testdata ());
|
||||
fn += "/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ());
|
||||
|
||||
EXPECT_EQ ((e2 & e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ ((e2 - e2).to_string (), "");
|
||||
EXPECT_EQ (e2.andnot (e2).first.to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.andnot (e2).second.to_string (), "");
|
||||
EXPECT_EQ ((e2 | e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ ((e2 ^ e2).to_string (), "");
|
||||
EXPECT_EQ (e2.in (e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.in (e2, true).to_string (), "");
|
||||
EXPECT_EQ (e2.in_and_out (e2).first.to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.in_and_out (e2).second.to_string (), "");
|
||||
EXPECT_EQ (e2.selected_interacting (e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.selected_not_interacting (e2).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_interacting_differential (e2).first.to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.selected_interacting_differential (e2).second.to_string (), "");
|
||||
EXPECT_EQ ((e2.selected_interacting (e2, (size_t) 1, (size_t) 3) ^ e2).to_string (), "");
|
||||
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).first ^ e2).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).second.to_string (), "");
|
||||
EXPECT_EQ (e2.selected_interacting (e2, (size_t) 4).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 4).first.to_string (), "");
|
||||
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 4).second ^ e2).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_inside (e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.selected_not_inside (e2).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_inside_differential (e2).first.to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.selected_inside_differential (e2).second.to_string (), "");
|
||||
EXPECT_EQ (e2.selected_outside (e2).to_string (), "");
|
||||
EXPECT_EQ (e2.selected_not_outside (e2).to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.selected_outside_differential (e2).first.to_string (), "");
|
||||
EXPECT_EQ (e2.selected_outside_differential (e2).second.to_string (), e2.to_string ());
|
||||
EXPECT_EQ (e2.pull_interacting (e2).to_string (), e2.to_string ());
|
||||
}
|
||||
|
||||
TEST(deep_edges_and_cheats)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2649,6 +2649,66 @@ TEST(101_DeepFlatCollaboration)
|
|||
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au101.gds");
|
||||
}
|
||||
|
||||
TEST(102_SameInputs)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testdata ());
|
||||
fn += "/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
|
||||
|
||||
EXPECT_EQ ((r2 & r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ ((r2 - r2).to_string (), "");
|
||||
EXPECT_EQ (r2.andnot (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.andnot (r2).second.to_string (), "");
|
||||
EXPECT_EQ ((r2 | r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ ((r2 ^ r2).to_string (), "");
|
||||
EXPECT_EQ (r2.in (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.in (r2, true).to_string (), "");
|
||||
EXPECT_EQ (r2.in_and_out (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.in_and_out (r2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_enclosing (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_not_enclosing (r2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_enclosing_differential (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_enclosing_differential (r2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_not_interacting (r2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 1, (size_t) 2).to_string (), r2.merged ().to_string ());
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).first.to_string (), r2.merged ().to_string ());
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).first.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).second.to_string (), r2.merged ().to_string ());
|
||||
EXPECT_EQ (r2.selected_inside (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_not_inside (r2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_inside_differential (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_inside_differential (r2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_outside (r2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_not_outside (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_outside_differential (r2).first.to_string (), "");
|
||||
EXPECT_EQ (r2.selected_outside_differential (r2).second.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_overlapping (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_not_overlapping (r2).to_string (), "");
|
||||
EXPECT_EQ (r2.selected_overlapping_differential (r2).first.to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.selected_overlapping_differential (r2).second.to_string (), "");
|
||||
EXPECT_EQ (r2.pull_inside (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.pull_overlapping (r2).to_string (), r2.to_string ());
|
||||
EXPECT_EQ (r2.pull_interacting (r2).to_string (), r2.to_string ());
|
||||
}
|
||||
|
||||
TEST(issue_277)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
Loading…
Reference in New Issue