From a9cd9ac122c49ac10e070fdd45a5f1e009638947 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 12 May 2020 20:44:39 +0200 Subject: [PATCH] First implementation of texts collection. --- src/db/db/db.pro | 21 +- src/db/db/dbAsIfFlatTexts.cc | 277 ++++++++++++ src/db/db/dbAsIfFlatTexts.h | 88 ++++ src/db/db/dbDeepShapeStore.cc | 58 +-- src/db/db/dbDeepShapeStore.h | 9 + src/db/db/dbDeepTexts.cc | 316 ++++++++++++++ src/db/db/dbDeepTexts.h | 102 +++++ src/db/db/dbEdges.h | 1 + src/db/db/dbEmptyTexts.cc | 88 ++++ src/db/db/dbEmptyTexts.h | 85 ++++ src/db/db/dbFlatTexts.cc | 220 ++++++++++ src/db/db/dbFlatTexts.h | 171 ++++++++ src/db/db/dbHierarchyBuilder.cc | 14 + src/db/db/dbHierarchyBuilder.h | 14 + src/db/db/dbOriginalLayerTexts.cc | 197 +++++++++ src/db/db/dbOriginalLayerTexts.h | 75 ++++ src/db/db/dbRegion.h | 1 + src/db/db/dbTexts.cc | 207 +++++++++ src/db/db/dbTexts.h | 670 ++++++++++++++++++++++++++++++ src/db/db/dbTextsDelegate.cc | 68 +++ src/db/db/dbTextsDelegate.h | 140 +++++++ src/db/db/dbTextsUtils.cc | 31 ++ src/db/db/dbTextsUtils.h | 154 +++++++ src/db/db/gsiDeclDbTexts.cc | 470 +++++++++++++++++++++ 24 files changed, 3424 insertions(+), 53 deletions(-) create mode 100644 src/db/db/dbAsIfFlatTexts.cc create mode 100644 src/db/db/dbAsIfFlatTexts.h create mode 100644 src/db/db/dbDeepTexts.cc create mode 100644 src/db/db/dbDeepTexts.h create mode 100644 src/db/db/dbEmptyTexts.cc create mode 100644 src/db/db/dbEmptyTexts.h create mode 100644 src/db/db/dbFlatTexts.cc create mode 100644 src/db/db/dbFlatTexts.h create mode 100644 src/db/db/dbOriginalLayerTexts.cc create mode 100644 src/db/db/dbOriginalLayerTexts.h create mode 100644 src/db/db/dbTexts.cc create mode 100644 src/db/db/dbTexts.h create mode 100644 src/db/db/dbTextsDelegate.cc create mode 100644 src/db/db/dbTextsDelegate.h create mode 100644 src/db/db/dbTextsUtils.cc create mode 100644 src/db/db/dbTextsUtils.h create mode 100644 src/db/db/gsiDeclDbTexts.cc diff --git a/src/db/db/db.pro b/src/db/db/db.pro index ea36ff395..0d7823d6c 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -184,7 +184,16 @@ SOURCES = \ dbLayoutVsSchematic.cc \ gsiDeclDbNetlistCrossReference.cc \ gsiDeclDbLayoutVsSchematic.cc \ - dbNetlistObject.cc + dbNetlistObject.cc \ + gsiDeclDbTexts.cc \ + dbTexts.cc \ + dbDeepTexts.cc \ + dbAsIfFlatTexts.cc \ + dbTextsDelegate.cc \ + dbEmptyTexts.cc \ + dbFlatTexts.cc \ + dbTextsUtils.cc \ + dbOriginalLayerTexts.cc HEADERS = \ dbArray.h \ @@ -331,7 +340,15 @@ HEADERS = \ dbLayoutVsSchematicReader.h \ dbLayoutVsSchematicFormatDefs.h \ dbLayoutVsSchematic.h \ - dbNetlistObject.h + dbNetlistObject.h \ + dbTexts.h \ + dbDeepTexts.h \ + dbAsIfFlatTexts.h \ + dbTextsDelegate.h \ + dbEmptyTexts.h \ + dbFlatTexts.h \ + dbTextsUtils.h \ + dbOriginalLayerTexts.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc new file mode 100644 index 000000000..968988311 --- /dev/null +++ b/src/db/db/dbAsIfFlatTexts.cc @@ -0,0 +1,277 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbAsIfFlatTexts.h" +#include "dbFlatTexts.h" +#include "dbFlatRegion.h" +#include "dbFlatEdges.h" +#include "dbEmptyTexts.h" +#include "dbTexts.h" +#include "dbBoxConvert.h" + +#include + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- +// AsIfFlagTexts implementation + +AsIfFlatTexts::AsIfFlatTexts () + : TextsDelegate (), m_bbox_valid (false) +{ + // .. nothing yet .. +} + +AsIfFlatTexts::~AsIfFlatTexts () +{ + // .. nothing yet .. +} + +std::string +AsIfFlatTexts::to_string (size_t nmax) const +{ + std::ostringstream os; + TextsIterator p (begin ()); + bool first = true; + for ( ; ! p.at_end () && nmax != 0; ++p, --nmax) { + if (! first) { + os << ";"; + } + first = false; + os << p->to_string (); + } + if (! p.at_end ()) { + os << "..."; + } + return os.str (); +} + +TextsDelegate * +AsIfFlatTexts::in (const Texts &other, bool invert) const +{ + std::set op; + for (TextsIterator o (other.begin ()); ! o.at_end (); ++o) { + op.insert (*o); + } + + std::auto_ptr new_texts (new FlatTexts (false)); + + for (TextsIterator o (begin ()); ! o.at_end (); ++o) { + if ((op.find (*o) == op.end ()) == invert) { + new_texts->insert (*o); + } + } + + return new_texts.release (); +} + +size_t +AsIfFlatTexts::size () const +{ + size_t n = 0; + for (TextsIterator t (begin ()); ! t.at_end (); ++t) { + ++n; + } + return n; +} + +Box AsIfFlatTexts::bbox () const +{ + if (! m_bbox_valid) { + m_bbox = compute_bbox (); + m_bbox_valid = true; + } + return m_bbox; +} + +Box AsIfFlatTexts::compute_bbox () const +{ + db::Box b; + for (TextsIterator t (begin ()); ! t.at_end (); ++t) { + b += t->box (); + } + return b; +} + +void AsIfFlatTexts::update_bbox (const db::Box &b) +{ + m_bbox = b; + m_bbox_valid = true; +} + +void AsIfFlatTexts::invalidate_bbox () +{ + m_bbox_valid = false; +} + +TextsDelegate * +AsIfFlatTexts::filtered (const TextFilterBase &filter) const +{ + std::auto_ptr new_texts (new FlatTexts ()); + + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + if (filter.selected (*p)) { + new_texts->insert (*p); + } + } + + return new_texts.release (); +} + +RegionDelegate * +AsIfFlatTexts::polygons (db::Coord e) const +{ + std::auto_ptr output (new FlatRegion ()); + + for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) { + db::Box box = tp->box (); + box.enlarge (db::Vector (e, e)); + output->insert (db::Polygon (box)); + } + + return output.release (); +} + +EdgesDelegate * +AsIfFlatTexts::edges () const +{ + std::auto_ptr output (new FlatEdges ()); + + for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) { + db::Box box = tp->box (); + output->insert (db::Edge (box.p1 (), box.p2 ())); + } + + return output.release (); +} + +TextsDelegate * +AsIfFlatTexts::add (const Texts &other) const +{ + FlatTexts *other_flat = dynamic_cast (other.delegate ()); + if (other_flat) { + + std::auto_ptr new_texts (new FlatTexts (*other_flat)); + new_texts->invalidate_cache (); + + size_t n = new_texts->raw_texts ().size () + size (); + + new_texts->reserve (n); + + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + new_texts->raw_texts ().insert (*p); + } + + return new_texts.release (); + + } else { + + std::auto_ptr new_texts (new FlatTexts ()); + + size_t n = size () + other.size (); + + new_texts->reserve (n); + + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + new_texts->raw_texts ().insert (*p); + } + for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) { + new_texts->raw_texts ().insert (*p); + } + + return new_texts.release (); + + } +} + +bool +AsIfFlatTexts::equals (const Texts &other) const +{ + if (empty () != other.empty ()) { + return false; + } + if (size () != other.size ()) { + return false; + } + TextsIterator o1 (begin ()); + TextsIterator o2 (other.begin ()); + while (! o1.at_end () && ! o2.at_end ()) { + if (*o1 != *o2) { + return false; + } + ++o1; + ++o2; + } + return true; +} + +bool +AsIfFlatTexts::less (const Texts &other) const +{ + if (empty () != other.empty ()) { + return empty () < other.empty (); + } + if (size () != other.size ()) { + return (size () < other.size ()); + } + TextsIterator o1 (begin ()); + TextsIterator o2 (other.begin ()); + while (! o1.at_end () && ! o2.at_end ()) { + if (*o1 != *o2) { + return *o1 < *o2; + } + ++o1; + ++o2; + } + return false; +} + +void +AsIfFlatTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const +{ + // improves performance when inserting an original layout into the same layout + db::LayoutLocker locker (layout); + + db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer); + for (TextsIterator t (begin ()); ! t.at_end (); ++t) { + shapes.insert (*t); + } +} + +void +AsIfFlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const +{ + // improves performance when inserting an original layout into the same layout + db::LayoutLocker locker (layout); + + db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer); + for (TextsIterator t (begin ()); ! t.at_end (); ++t) { + db::Box box = t->box (); + box.enlarge (db::Vector (enl, enl)); + shapes.insert (db::SimplePolygon (box)); + } +} + +} + diff --git a/src/db/db/dbAsIfFlatTexts.h b/src/db/db/dbAsIfFlatTexts.h new file mode 100644 index 000000000..a2236cc7f --- /dev/null +++ b/src/db/db/dbAsIfFlatTexts.h @@ -0,0 +1,88 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbAsIfFlatTexts +#define HDR_dbAsIfFlatTexts + +#include "dbCommon.h" + +#include "dbTextsDelegate.h" + +namespace db { + +/** + * @brief Provides default flat implementations + */ +class DB_PUBLIC AsIfFlatTexts + : public TextsDelegate +{ +public: + AsIfFlatTexts (); + virtual ~AsIfFlatTexts (); + + virtual size_t size () const; + virtual std::string to_string (size_t) const; + virtual Box bbox () const; + + virtual TextsDelegate *filter_in_place (const TextFilterBase &filter) + { + return filtered (filter); + } + + virtual TextsDelegate *filtered (const TextFilterBase &) const; + + virtual TextsDelegate *add_in_place (const Texts &other) + { + return add (other); + } + + virtual TextsDelegate *add (const Texts &other) const; + + virtual RegionDelegate *polygons (db::Coord e) const; + virtual EdgesDelegate *edges () const; + + virtual TextsDelegate *in (const Texts &, bool) const; + + virtual bool equals (const Texts &other) const; + virtual bool less (const Texts &other) const; + + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; + virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const; + +protected: + void update_bbox (const db::Box &box); + void invalidate_bbox (); + +private: + AsIfFlatTexts &operator= (const AsIfFlatTexts &other); + + mutable bool m_bbox_valid; + mutable db::Box m_bbox; + + virtual db::Box compute_bbox () const; +}; + +} + +#endif + diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index c1fcb9009..061b4b180 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -807,64 +807,20 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans) { - unsigned int layout_index = layout_for_iter (si, trans); - - db::Layout &layout = m_layouts[layout_index]->layout; - db::HierarchyBuilder &builder = m_layouts[layout_index]->builder; - - unsigned int layer_index = init_layer (layout, si); - builder.set_target_layer (layer_index); - - // The chain of operators for producing edges db::EdgeBuildingHierarchyBuilderShapeReceiver refs (as_edges); - - // Build the working hierarchy from the recursive shape iterator - try { - - tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy"))); - db::LayoutLocker ll (&layout, true /*no update*/); - - builder.set_shape_receiver (&refs); - db::RecursiveShapeIterator (si).push (& builder); - builder.set_shape_receiver (0); - - } catch (...) { - builder.set_shape_receiver (0); - throw; - } - - return DeepLayer (this, layout_index, layer_index); + return create_custom_layer (si, &refs, trans); } DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans) { - unsigned int layout_index = layout_for_iter (si, trans); - - db::Layout &layout = m_layouts[layout_index]->layout; - db::HierarchyBuilder &builder = m_layouts[layout_index]->builder; - - unsigned int layer_index = init_layer (layout, si); - builder.set_target_layer (layer_index); - - // The chain of operators for producing the edge pairs db::EdgePairBuildingHierarchyBuilderShapeReceiver refs; + return create_custom_layer (si, &refs, trans); +} - // Build the working hierarchy from the recursive shape iterator - try { - - tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy"))); - db::LayoutLocker ll (&layout, true /*no update*/); - - builder.set_shape_receiver (&refs); - db::RecursiveShapeIterator (si).push (& builder); - builder.set_shape_receiver (0); - - } catch (...) { - builder.set_shape_receiver (0); - throw; - } - - return DeepLayer (this, layout_index, layer_index); +DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans) +{ + db::TextBuildingHierarchyBuilderShapeReceiver refs; + return create_custom_layer (si, &refs, trans); } void diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 3290d5573..3c4e678ec 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -395,6 +395,15 @@ public: */ DeepLayer create_edge_pair_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ()); + /** + * @brief Inserts an text layer into the deep shape store + * + * This method will create a new layer inside the deep shape store as a + * working copy of the original layer. This method creates a layer + * for texts. + */ + DeepLayer create_text_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ()); + /** * @brief Inserts a polygon layer into the deep shape store using a custom preparation pipeline * diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc new file mode 100644 index 000000000..479ee93c5 --- /dev/null +++ b/src/db/db/dbDeepTexts.cc @@ -0,0 +1,316 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbDeepTexts.h" +#include "dbCellGraphUtils.h" +#include "dbDeepEdges.h" +#include "dbDeepRegion.h" +#include "dbCellMapping.h" +#include "dbLayoutUtils.h" + +#include + +namespace db +{ + +/** + * @brief An iterator delegate for the deep text collection + * TODO: this is kind of redundant with OriginalLayerIterator .. + */ +class DB_PUBLIC DeepTextsIterator + : public TextsIteratorDelegate +{ +public: + DeepTextsIterator (const db::RecursiveShapeIterator &iter) + : m_iter (iter) + { + set (); + } + + virtual ~DeepTextsIterator () { } + + virtual bool at_end () const + { + return m_iter.at_end (); + } + + virtual void increment () + { + ++m_iter; + set (); + } + + virtual const value_type *get () const + { + return &m_text; + } + + virtual TextsIteratorDelegate *clone () const + { + return new DeepTextsIterator (*this); + } + +private: + friend class Texts; + + db::RecursiveShapeIterator m_iter; + mutable value_type m_text; + + void set () const { + if (! m_iter.at_end ()) { + m_iter.shape ().text (m_text); + m_text.transform (m_iter.trans ()); + } + } +}; + + +DeepTexts::DeepTexts () + : AsIfFlatTexts (), m_deep_layer () +{ + // .. nothing yet .. +} + +DeepTexts::DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss) + : AsIfFlatTexts (), m_deep_layer (dss.create_text_layer (si)) +{ + // .. nothing yet .. +} + +DeepTexts::DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans) + : AsIfFlatTexts (), m_deep_layer (dss.create_text_layer (si, trans)) +{ + // .. nothing yet .. +} + +DeepTexts::DeepTexts (const DeepTexts &other) + : AsIfFlatTexts (other), + m_deep_layer (other.m_deep_layer.copy ()) +{ + // .. nothing yet .. +} + +DeepTexts::DeepTexts (const DeepLayer &dl) + : AsIfFlatTexts (), m_deep_layer (dl) +{ + // .. nothing yet .. +} + +DeepTexts::~DeepTexts () +{ + // .. nothing yet .. +} + +TextsDelegate *DeepTexts::clone () const +{ + return new DeepTexts (*this); +} + +TextsIteratorDelegate *DeepTexts::begin () const +{ + return new DeepTextsIterator (begin_iter ().first); +} + +std::pair DeepTexts::begin_iter () const +{ + const db::Layout &layout = m_deep_layer.layout (); + if (layout.cells () == 0) { + + return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); + + } else { + + const db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ()); + return std::make_pair (iter, db::ICplxTrans ()); + + } +} + +size_t DeepTexts::size () const +{ + size_t n = 0; + + const db::Layout &layout = m_deep_layer.layout (); + db::CellCounter cc (&layout); + for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { + n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size (); + } + + return n; +} + +std::string DeepTexts::to_string (size_t nmax) const +{ + return db::AsIfFlatTexts::to_string (nmax); +} + +Box DeepTexts::bbox () const +{ + return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ()); +} + +bool DeepTexts::empty () const +{ + return begin_iter ().first.at_end (); +} + +const db::Text *DeepTexts::nth (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat text collections"))); +} + +bool DeepTexts::has_valid_texts () const +{ + return false; +} + +const db::RecursiveShapeIterator *DeepTexts::iter () const +{ + return 0; +} + +TextsDelegate * +DeepTexts::add_in_place (const Texts &other) +{ + if (other.empty ()) { + return this; + } + + const DeepTexts *other_deep = dynamic_cast (other.delegate ()); + if (other_deep) { + + deep_layer ().add_from (other_deep->deep_layer ()); + + } else { + + // non-deep to deep merge (flat) + + db::Shapes &shapes = deep_layer ().initial_cell ().shapes (deep_layer ().layer ()); + for (db::Texts::const_iterator p = other.begin (); ! p.at_end (); ++p) { + shapes.insert (*p); + } + + } + + return this; +} + +TextsDelegate *DeepTexts::add (const Texts &other) const +{ + if (other.empty ()) { + return clone (); + } else if (empty ()) { + return other.delegate ()->clone (); + } else { + DeepTexts *new_texts = dynamic_cast (clone ()); + new_texts->add_in_place (other); + return new_texts; + } +} + +TextsDelegate *DeepTexts::filter_in_place (const TextFilterBase &filter) +{ + // TODO: implement + return AsIfFlatTexts::filter_in_place (filter); +} + +TextsDelegate *DeepTexts::filtered (const TextFilterBase &filter) const +{ + // TODO: implement + return AsIfFlatTexts::filtered (filter); +} + +RegionDelegate *DeepTexts::polygons (db::Coord e) const +{ + db::DeepLayer new_layer = m_deep_layer.derived (); + db::Layout &layout = const_cast (m_deep_layer.layout ()); + + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + db::Shapes &output = c->shapes (new_layer.layer ()); + for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::Texts); ! s.at_end (); ++s) { + db::Box box = s->bbox (); + box.enlarge (db::Vector (e, e)); + db::Polygon poly (box); + output.insert (db::PolygonRef (poly, layout.shape_repository ())); + } + } + + return new db::DeepRegion (new_layer); +} + +EdgesDelegate *DeepTexts::edges () const +{ + db::DeepLayer new_layer = m_deep_layer.derived (); + db::Layout &layout = const_cast (m_deep_layer.layout ()); + + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + db::Shapes &output = c->shapes (new_layer.layer ()); + for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::Texts); ! s.at_end (); ++s) { + db::Box box = s->bbox (); + output.insert (db::Edge (box.p1 (), box.p2 ())); + } + } + + return new db::DeepEdges (new_layer); +} + +TextsDelegate *DeepTexts::in (const Texts &other, bool invert) const +{ + // TODO: implement + return AsIfFlatTexts::in (other, invert); +} + +bool DeepTexts::equals (const Texts &other) const +{ + const DeepTexts *other_delegate = dynamic_cast (other.delegate ()); + if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout () + && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) { + return true; + } else { + return AsIfFlatTexts::equals (other); + } +} + +bool DeepTexts::less (const Texts &other) const +{ + const DeepTexts *other_delegate = dynamic_cast (other.delegate ()); + if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) { + return other_delegate->m_deep_layer.layer () < m_deep_layer.layer (); + } else { + return AsIfFlatTexts::less (other); + } +} + +void DeepTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const +{ + m_deep_layer.insert_into (layout, into_cell, into_layer); +} + +void DeepTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const +{ + m_deep_layer.insert_into_as_polygons (layout, into_cell, into_layer, enl); +} + + +} diff --git a/src/db/db/dbDeepTexts.h b/src/db/db/dbDeepTexts.h new file mode 100644 index 000000000..bac1c081b --- /dev/null +++ b/src/db/db/dbDeepTexts.h @@ -0,0 +1,102 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbDeepTexts +#define HDR_dbDeepTexts + +#include "dbCommon.h" + +#include "dbAsIfFlatTexts.h" +#include "dbDeepShapeStore.h" +#include "dbTexts.h" + +namespace db { + +/** + * @brief Provides hierarchical edges implementation + */ +class DB_PUBLIC DeepTexts + : public db::AsIfFlatTexts +{ +public: + DeepTexts (); + DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss); + DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans); + + DeepTexts (const DeepTexts &other); + DeepTexts (const DeepLayer &dl); + + virtual ~DeepTexts (); + + TextsDelegate *clone () const; + + virtual TextsIteratorDelegate *begin () const; + virtual std::pair begin_iter () const; + + virtual size_t size () const; + virtual std::string to_string (size_t) const; + virtual Box bbox () const; + virtual bool empty () const; + virtual const db::Text *nth (size_t n) const; + virtual bool has_valid_texts () const; + virtual const db::RecursiveShapeIterator *iter () const; + + virtual TextsDelegate *filter_in_place (const TextFilterBase &filter); + virtual TextsDelegate *filtered (const TextFilterBase &) const; + + virtual TextsDelegate *add_in_place (const Texts &other); + virtual TextsDelegate *add (const Texts &other) const; + + virtual RegionDelegate *polygons (db::Coord e) const; + virtual EdgesDelegate *edges () const; + + virtual TextsDelegate *in (const Texts &, bool) const; + + virtual bool equals (const Texts &other) const; + virtual bool less (const Texts &other) const; + + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; + virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const; + + const DeepLayer &deep_layer () const + { + return m_deep_layer; + } + + DeepLayer &deep_layer () + { + return m_deep_layer; + } + +private: + DeepTexts &operator= (const DeepTexts &other); + + DeepLayer m_deep_layer; + + void init (); +}; + +} + +#endif + diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 3634e5d4e..c2d304ba0 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -1301,6 +1301,7 @@ public: private: friend class EdgePairs; + friend class Texts; EdgesDelegate *mp_delegate; diff --git a/src/db/db/dbEmptyTexts.cc b/src/db/db/dbEmptyTexts.cc new file mode 100644 index 000000000..1037a078b --- /dev/null +++ b/src/db/db/dbEmptyTexts.cc @@ -0,0 +1,88 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbEmptyTexts.h" +#include "dbEmptyRegion.h" +#include "dbEmptyEdges.h" +#include "dbTexts.h" + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- + +EmptyTexts::EmptyTexts () +{ + // .. nothing yet .. +} + +EmptyTexts::EmptyTexts (const EmptyTexts &other) + : TextsDelegate (other) +{ + // .. nothing yet .. +} + +TextsDelegate * +EmptyTexts::clone () const +{ + return new EmptyTexts (*this); +} + +RegionDelegate * +EmptyTexts::polygons (db::Coord) const +{ + return new EmptyRegion (); +} + +EdgesDelegate * +EmptyTexts::edges () const +{ + return new EmptyEdges (); +} + +TextsDelegate * +EmptyTexts::add_in_place (const Texts &other) +{ + return add (other); +} + +TextsDelegate * +EmptyTexts::add (const Texts &other) const +{ + return other.delegate ()->clone (); +} + +bool +EmptyTexts::equals (const Texts &other) const +{ + return other.empty (); +} + +bool +EmptyTexts::less (const Texts &other) const +{ + return other.empty () ? false : true; +} + +} + diff --git a/src/db/db/dbEmptyTexts.h b/src/db/db/dbEmptyTexts.h new file mode 100644 index 000000000..59520928b --- /dev/null +++ b/src/db/db/dbEmptyTexts.h @@ -0,0 +1,85 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbEmptyTexts +#define HDR_dbEmptyTexts + +#include "dbCommon.h" + +#include "dbTextsDelegate.h" +#include "dbRecursiveShapeIterator.h" + +namespace db { + +/** + * @brief The delegate for the actual edge set implementation + */ +class DB_PUBLIC EmptyTexts + : public TextsDelegate +{ +public: + EmptyTexts (); + EmptyTexts (const EmptyTexts &other); + + virtual TextsDelegate *clone () const; + + virtual std::string to_string (size_t) const { return std::string (); } + + virtual TextsIteratorDelegate *begin () const { return 0; } + virtual std::pair begin_iter () const { return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); } + + virtual bool empty () const { return true; } + virtual size_t size () const { return 0; } + + virtual Box bbox () const { return Box (); } + + virtual TextsDelegate *filter_in_place (const TextFilterBase &) { return this; } + virtual TextsDelegate *filtered (const TextFilterBase &) const { return new EmptyTexts (); } + + virtual RegionDelegate *polygons (db::Coord e) const; + virtual EdgesDelegate *edges () const; + + virtual TextsDelegate *add_in_place (const Texts &other); + virtual TextsDelegate *add (const Texts &other) const; + + virtual TextsDelegate *in (const Texts &, bool) const { return new EmptyTexts (); } + + virtual const db::Text *nth (size_t) const { tl_assert (false); } + virtual bool has_valid_texts () const { return true; } + + virtual const db::RecursiveShapeIterator *iter () const { return 0; } + + virtual bool equals (const Texts &other) const; + virtual bool less (const Texts &other) const; + + virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { } + virtual void insert_into_as_polygons (Layout *, db::cell_index_type, unsigned int, db::Coord) const { } + +private: + EmptyTexts &operator= (const EmptyTexts &other); +}; + +} + +#endif + diff --git a/src/db/db/dbFlatTexts.cc b/src/db/db/dbFlatTexts.cc new file mode 100644 index 000000000..4e4152d3a --- /dev/null +++ b/src/db/db/dbFlatTexts.cc @@ -0,0 +1,220 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbFlatTexts.h" +#include "dbEmptyTexts.h" +#include "dbTexts.h" + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- +// FlatTexts implementation + +FlatTexts::FlatTexts () + : AsIfFlatTexts (), m_texts (false) +{ + // .. nothing yet .. +} + +FlatTexts::~FlatTexts () +{ + // .. nothing yet .. +} + +FlatTexts::FlatTexts (const FlatTexts &other) + : AsIfFlatTexts (other), m_texts (false) +{ + m_texts = other.m_texts; +} + +FlatTexts::FlatTexts (const db::Shapes &texts) + : AsIfFlatTexts (), m_texts (texts) +{ + // .. nothing yet .. +} + +void FlatTexts::invalidate_cache () +{ + invalidate_bbox (); +} + +void FlatTexts::reserve (size_t n) +{ + m_texts.reserve (db::Text::tag (), n); +} + +TextsIteratorDelegate *FlatTexts::begin () const +{ + return new FlatTextsIterator (m_texts.get_layer ().begin (), m_texts.get_layer ().end ()); +} + +std::pair FlatTexts::begin_iter () const +{ + return std::make_pair (db::RecursiveShapeIterator (m_texts), db::ICplxTrans ()); +} + +bool FlatTexts::empty () const +{ + return m_texts.empty (); +} + +size_t FlatTexts::size () const +{ + return m_texts.size (); +} + +Box FlatTexts::compute_bbox () const +{ + m_texts.update_bbox (); + return m_texts.bbox (); +} + +TextsDelegate * +FlatTexts::filter_in_place (const TextFilterBase &filter) +{ + text_iterator_type pw = m_texts.get_layer ().begin (); + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + if (filter.selected (*p)) { + if (pw == m_texts.get_layer ().end ()) { + m_texts.get_layer ().insert (*p); + pw = m_texts.get_layer ().end (); + } else { + m_texts.get_layer ().replace (pw++, *p); + } + } + } + + m_texts.get_layer ().erase (pw, m_texts.get_layer ().end ()); + + return this; +} + +TextsDelegate *FlatTexts::add (const Texts &other) const +{ + std::auto_ptr new_texts (new FlatTexts (*this)); + new_texts->invalidate_cache (); + + FlatTexts *other_flat = dynamic_cast (other.delegate ()); + if (other_flat) { + + new_texts->raw_texts ().insert (other_flat->raw_texts ().get_layer ().begin (), other_flat->raw_texts ().get_layer ().end ()); + + } else { + + size_t n = new_texts->raw_texts ().size (); + for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) { + ++n; + } + + new_texts->raw_texts ().reserve (db::Text::tag (), n); + + for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) { + new_texts->raw_texts ().insert (*p); + } + + } + + return new_texts.release (); +} + +TextsDelegate *FlatTexts::add_in_place (const Texts &other) +{ + invalidate_cache (); + + FlatTexts *other_flat = dynamic_cast (other.delegate ()); + if (other_flat) { + + m_texts.insert (other_flat->raw_texts ().get_layer ().begin (), other_flat->raw_texts ().get_layer ().end ()); + + } else { + + size_t n = m_texts.size (); + for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) { + ++n; + } + + m_texts.reserve (db::Text::tag (), n); + + for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) { + m_texts.insert (*p); + } + + } + + return this; +} + +const db::Text *FlatTexts::nth (size_t n) const +{ + return n < m_texts.size () ? &m_texts.get_layer ().begin () [n] : 0; +} + +bool FlatTexts::has_valid_texts () const +{ + return true; +} + +const db::RecursiveShapeIterator *FlatTexts::iter () const +{ + return 0; +} + +void +FlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const +{ + db::Shapes &out = layout->cell (into_cell).shapes (into_layer); + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + db::Box box = p->box (); + box.enlarge (db::Vector (enl, enl)); + out.insert (db::SimplePolygon (box)); + } +} + +void +FlatTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const +{ + layout->cell (into_cell).shapes (into_layer).insert (m_texts); +} + +void +FlatTexts::insert (const db::Text &t) +{ + m_texts.insert (t); + invalidate_cache (); +} + +void +FlatTexts::insert (const db::Shape &shape) +{ + if (shape.is_edge_pair ()) { + + db::Text t; + shape.text (t); + insert (t); + + } +} + +} + diff --git a/src/db/db/dbFlatTexts.h b/src/db/db/dbFlatTexts.h new file mode 100644 index 000000000..38a249fbe --- /dev/null +++ b/src/db/db/dbFlatTexts.h @@ -0,0 +1,171 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbFlatTexts +#define HDR_dbFlatTexts + +#include "dbCommon.h" + +#include "dbAsIfFlatTexts.h" +#include "dbShapes.h" + +namespace db { + +/** + * @brief An iterator delegate for the flat text set + */ +class DB_PUBLIC FlatTextsIterator + : public TextsIteratorDelegate +{ +public: + typedef db::layer edge_pair_layer_type; + typedef edge_pair_layer_type::iterator iterator_type; + + FlatTextsIterator (iterator_type from, iterator_type to) + : m_from (from), m_to (to) + { + // .. nothing yet .. + } + + virtual bool at_end () const + { + return m_from == m_to; + } + + virtual void increment () + { + ++m_from; + } + + virtual const value_type *get () const + { + return m_from.operator-> (); + } + + virtual TextsIteratorDelegate *clone () const + { + return new FlatTextsIterator (*this); + } + +private: + friend class Texts; + + iterator_type m_from, m_to; +}; + +/** + * @brief The delegate for the actual text set implementation + */ +class DB_PUBLIC FlatTexts + : public AsIfFlatTexts +{ +public: + typedef db::layer text_layer_type; + typedef text_layer_type::iterator text_iterator_type; + + FlatTexts (); + FlatTexts (const db::Shapes &texts); + + FlatTexts (const FlatTexts &other); + + virtual ~FlatTexts (); + + TextsDelegate *clone () const + { + return new FlatTexts (*this); + } + + void reserve (size_t); + + virtual TextsIteratorDelegate *begin () const; + virtual std::pair begin_iter () const; + + virtual bool empty () const; + virtual size_t size () const; + + virtual TextsDelegate *filter_in_place (const TextFilterBase &filter); + + virtual TextsDelegate *add_in_place (const Texts &other); + virtual TextsDelegate *add (const Texts &other) const; + + virtual const db::Text *nth (size_t n) const; + virtual bool has_valid_texts () const; + + virtual const db::RecursiveShapeIterator *iter () const; + + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; + virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const; + + void insert (const db::Text &text); + void insert (const db::Shape &shape); + + template + void insert (const db::Shape &shape, const T &trans) + { + if (shape.is_edge_pair ()) { + + db::Text t; + shape.text (t); + t.transform (trans); + insert (t); + + } + } + + template + void insert_seq (const Iter &seq) + { + for (Iter i = seq; ! i.at_end (); ++i) { + insert (*i); + } + } + + template + void transform (const Trans &trans) + { + if (! trans.is_unity ()) { + for (text_iterator_type p = m_texts.template get_layer ().begin (); p != m_texts.template get_layer ().end (); ++p) { + m_texts.get_layer ().replace (p, p->transformed (trans)); + } + invalidate_cache (); + } + } + + db::Shapes &raw_texts () { return m_texts; } + +protected: + virtual Box compute_bbox () const; + void invalidate_cache (); + +private: + friend class AsIfFlatTexts; + + FlatTexts &operator= (const FlatTexts &other); + + mutable db::Shapes m_texts; +}; + +} + +#endif + diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index a548c0341..50340a6a1 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -704,4 +704,18 @@ void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape } } +// --------------------------------------------------------------------------------------------- + +TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver () +{ + // .. nothing yet .. +} + +void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target) +{ + if (shape.is_text ()) { + target->insert (shape.text ().transformed (trans)); + } +} + } diff --git a/src/db/db/dbHierarchyBuilder.h b/src/db/db/dbHierarchyBuilder.h index b1d323dc7..9b115bb05 100644 --- a/src/db/db/dbHierarchyBuilder.h +++ b/src/db/db/dbHierarchyBuilder.h @@ -189,6 +189,20 @@ public: virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } }; +/** + * @brief An text-generating shape receiver that feeds a shapes array after turning the shapes into texts + */ +class DB_PUBLIC TextBuildingHierarchyBuilderShapeReceiver + : public HierarchyBuilderShapeReceiver +{ +public: + TextBuildingHierarchyBuilderShapeReceiver (); + + virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); + virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } + virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } +}; + /** * @brief A class building a hierarchy from a recursive shape iterator in push mode * diff --git a/src/db/db/dbOriginalLayerTexts.cc b/src/db/db/dbOriginalLayerTexts.cc new file mode 100644 index 000000000..ceb8534fd --- /dev/null +++ b/src/db/db/dbOriginalLayerTexts.cc @@ -0,0 +1,197 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbOriginalLayerTexts.h" +#include "dbTexts.h" +#include "tlInternational.h" + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- +// OriginalLayerTexts implementation + +namespace +{ + + class OriginalLayerTextsIterator + : public TextsIteratorDelegate + { + public: + OriginalLayerTextsIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans) + : m_rec_iter (iter), m_iter_trans (trans) + { + set (); + } + + virtual bool at_end () const + { + return m_rec_iter.at_end (); + } + + virtual void increment () + { + inc (); + set (); + } + + virtual const value_type *get () const + { + return &m_text; + } + + virtual TextsIteratorDelegate *clone () const + { + return new OriginalLayerTextsIterator (*this); + } + + private: + friend class Texts; + + db::RecursiveShapeIterator m_rec_iter; + db::ICplxTrans m_iter_trans; + db::Text m_text; + + void set () + { + while (! m_rec_iter.at_end () && ! m_rec_iter.shape ().is_text ()) { + ++m_rec_iter; + } + if (! m_rec_iter.at_end ()) { + m_rec_iter.shape ().text (m_text); + m_text.transform (m_iter_trans * m_rec_iter.trans ()); + } + } + + void inc () + { + if (! m_rec_iter.at_end ()) { + ++m_rec_iter; + } + } + }; + +} + +OriginalLayerTexts::OriginalLayerTexts () + : AsIfFlatTexts () +{ + init (); +} + +OriginalLayerTexts::OriginalLayerTexts (const OriginalLayerTexts &other) + : AsIfFlatTexts (other), + m_iter (other.m_iter), + m_iter_trans (other.m_iter_trans) +{ + // .. nothing yet .. +} + +OriginalLayerTexts::OriginalLayerTexts (const RecursiveShapeIterator &si) + : AsIfFlatTexts (), m_iter (si) +{ + init (); +} + +OriginalLayerTexts::OriginalLayerTexts (const RecursiveShapeIterator &si, const db::ICplxTrans &trans) + : AsIfFlatTexts (), m_iter (si), m_iter_trans (trans) +{ + init (); +} + +OriginalLayerTexts::~OriginalLayerTexts () +{ + // .. nothing yet .. +} + +TextsDelegate * +OriginalLayerTexts::clone () const +{ + return new OriginalLayerTexts (*this); +} + +TextsIteratorDelegate * +OriginalLayerTexts::begin () const +{ + return new OriginalLayerTextsIterator (m_iter, m_iter_trans); +} + +std::pair +OriginalLayerTexts::begin_iter () const +{ + return std::make_pair (m_iter, m_iter_trans); +} + +bool +OriginalLayerTexts::empty () const +{ + return m_iter.at_end (); +} + +const db::Text * +OriginalLayerTexts::nth (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat collections"))); +} + +bool +OriginalLayerTexts::has_valid_texts () const +{ + return false; +} + +const db::RecursiveShapeIterator * +OriginalLayerTexts::iter () const +{ + return &m_iter; +} + +bool +OriginalLayerTexts::equals (const Texts &other) const +{ + const OriginalLayerTexts *other_delegate = dynamic_cast (other.delegate ()); + if (other_delegate && other_delegate->m_iter == m_iter && other_delegate->m_iter_trans == m_iter_trans) { + return true; + } else { + return AsIfFlatTexts::equals (other); + } +} + +bool +OriginalLayerTexts::less (const Texts &other) const +{ + const OriginalLayerTexts *other_delegate = dynamic_cast (other.delegate ()); + if (other_delegate && other_delegate->m_iter == m_iter && other_delegate->m_iter_trans == m_iter_trans) { + return false; + } else { + return AsIfFlatTexts::less (other); + } +} + +void +OriginalLayerTexts::init () +{ + // .. nothing yet .. +} + +} diff --git a/src/db/db/dbOriginalLayerTexts.h b/src/db/db/dbOriginalLayerTexts.h new file mode 100644 index 000000000..32afd1e3f --- /dev/null +++ b/src/db/db/dbOriginalLayerTexts.h @@ -0,0 +1,75 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbOriginalLayerTexts +#define HDR_dbOriginalLayerTexts + +#include "dbCommon.h" + +#include "dbAsIfFlatTexts.h" +#include "dbShapes.h" +#include "dbRecursiveShapeIterator.h" + +namespace db { + +/** + * @brief An original layer text collection based on a RecursiveShapeIterator + */ +class DB_PUBLIC OriginalLayerTexts + : public AsIfFlatTexts +{ +public: + OriginalLayerTexts (); + OriginalLayerTexts (const OriginalLayerTexts &other); + OriginalLayerTexts (const RecursiveShapeIterator &si); + OriginalLayerTexts (const RecursiveShapeIterator &si, const db::ICplxTrans &trans); + virtual ~OriginalLayerTexts (); + + TextsDelegate *clone () const; + + virtual TextsIteratorDelegate *begin () const; + virtual std::pair begin_iter () const; + + virtual bool empty () const; + + virtual const db::Text *nth (size_t n) const; + virtual bool has_valid_texts () const; + + virtual const db::RecursiveShapeIterator *iter () const; + + virtual bool equals (const Texts &other) const; + virtual bool less (const Texts &other) const; + +private: + OriginalLayerTexts &operator= (const OriginalLayerTexts &other); + + mutable db::RecursiveShapeIterator m_iter; + db::ICplxTrans m_iter_trans; + + void init (); +}; + +} + +#endif + diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index bc8aa21df..5ac56c8d4 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -1612,6 +1612,7 @@ public: private: friend class Edges; friend class EdgePairs; + friend class Texts; RegionDelegate *mp_delegate; diff --git a/src/db/db/dbTexts.cc b/src/db/db/dbTexts.cc new file mode 100644 index 000000000..1ab956aa0 --- /dev/null +++ b/src/db/db/dbTexts.cc @@ -0,0 +1,207 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbCommon.h" + +#include "dbTexts.h" +#include "dbEmptyTexts.h" +#include "dbFlatTexts.h" +#include "dbDeepTexts.h" +#include "dbOriginalLayerTexts.h" +#include "dbEdges.h" +#include "dbRegion.h" + +#include "tlVariant.h" + +#include + +namespace db +{ + +Texts::Texts () + : mp_delegate (new EmptyTexts ()) +{ + // .. nothing yet .. +} + +Texts::~Texts () +{ + delete mp_delegate; + mp_delegate = 0; +} + +Texts::Texts (TextsDelegate *delegate) + : mp_delegate (delegate) +{ + // .. nothing yet .. +} + +Texts::Texts (const Texts &other) + : gsi::ObjectBase (), mp_delegate (other.mp_delegate->clone ()) +{ + // .. nothing yet .. +} + +Texts &Texts::operator= (const Texts &other) +{ + if (this != &other) { + set_delegate (other.mp_delegate->clone ()); + } + return *this; +} + +Texts::Texts (const RecursiveShapeIterator &si) +{ + mp_delegate = new OriginalLayerTexts (si); +} + +Texts::Texts (const RecursiveShapeIterator &si, const db::ICplxTrans &trans) +{ + mp_delegate = new OriginalLayerTexts (si, trans); +} + +Texts::Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss) +{ + mp_delegate = new DeepTexts (si, dss); +} + +Texts::Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans) +{ + mp_delegate = new DeepTexts (si, dss, trans); +} + +template +void Texts::insert (const Sh &shape) +{ + flat_texts ()->insert (shape); +} + +template DB_PUBLIC void Texts::insert (const db::Text &); + +void Texts::insert (const db::Shape &shape) +{ + flat_texts ()->insert (shape); +} + +template +void Texts::insert (const db::Shape &shape, const T &trans) +{ + flat_texts ()->insert (shape, trans); +} + +template DB_PUBLIC void Texts::insert (const db::Shape &, const db::ICplxTrans &); +template DB_PUBLIC void Texts::insert (const db::Shape &, const db::Trans &); +template DB_PUBLIC void Texts::insert (const db::Shape &, const db::Disp &); + +void Texts::clear () +{ + set_delegate (new EmptyTexts ()); +} + +void Texts::reserve (size_t n) +{ + flat_texts ()->reserve (n); +} + +template +Texts &Texts::transform (const T &trans) +{ + flat_texts ()->transform (trans); + return *this; +} + +// explicit instantiations +template DB_PUBLIC Texts &Texts::transform (const db::ICplxTrans &); +template DB_PUBLIC Texts &Texts::transform (const db::Trans &); +template DB_PUBLIC Texts &Texts::transform (const db::Disp &); + +const db::RecursiveShapeIterator & +Texts::iter () const +{ + static db::RecursiveShapeIterator def_iter; + const db::RecursiveShapeIterator *i = mp_delegate->iter (); + return *(i ? i : &def_iter); +} + +void Texts::polygons (Region &output, db::Coord e) const +{ + output.set_delegate (mp_delegate->polygons (e)); +} + +void Texts::edges (Edges &output) const +{ + output.set_delegate (mp_delegate->edges ()); +} + +void Texts::set_delegate (TextsDelegate *delegate) +{ + if (delegate != mp_delegate) { + delete mp_delegate; + mp_delegate = delegate; + } +} + +FlatTexts *Texts::flat_texts () +{ + FlatTexts *texts = dynamic_cast (mp_delegate); + if (! texts) { + texts = new FlatTexts (); + if (mp_delegate) { + texts->TextsDelegate::operator= (*mp_delegate); + texts->insert_seq (begin ()); + } + set_delegate (texts); + } + + return texts; +} + +} + +namespace tl +{ + template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::Texts &b) + { + db::Text ep; + + if (! ex.try_read (ep)) { + return false; + } + b.insert (ep); + + while (ex.test (";")) { + ex.read (ep); + b.insert (ep); + } + + return true; + } + + template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::Texts &b) + { + if (! test_extractor_impl (ex, b)) { + ex.error (tl::to_string (tr ("Expected an edge pair collection specification"))); + } + } +} + diff --git a/src/db/db/dbTexts.h b/src/db/db/dbTexts.h new file mode 100644 index 000000000..bfba8ac50 --- /dev/null +++ b/src/db/db/dbTexts.h @@ -0,0 +1,670 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbTexts +#define HDR_dbTexts + +#include "dbTextsDelegate.h" +#include "dbShape.h" +#include "dbRecursiveShapeIterator.h" + +#include "gsiObject.h" + +#include + +namespace db +{ + +class TextFilterBase; +class FlatTexts; +class EmptyTexts; +class Edges; +class Region; +class DeepShapeStore; +class TransformationReducer; + +/** + * @brief An text set iterator + * + * The iterator delivers the texts of the text set + */ +class DB_PUBLIC TextsIterator +{ +public: + typedef TextsIteratorDelegate::value_type value_type; + typedef const value_type &reference; + typedef const value_type *pointer; + typedef std::forward_iterator_tag iterator_category; + typedef void difference_type; + + /** + * @brief Default constructor + */ + TextsIterator () + : mp_delegate (0) + { + // .. nothing yet .. + } + + /** + * @brief Constructor from a delegate + * The iterator will take ownership over the delegate + */ + TextsIterator (TextsIteratorDelegate *delegate) + : mp_delegate (delegate) + { + // .. nothing yet .. + } + + /** + * @brief Destructor + */ + ~TextsIterator () + { + delete mp_delegate; + mp_delegate = 0; + } + + /** + * @brief Copy constructor and assignment + */ + TextsIterator (const TextsIterator &other) + : mp_delegate (0) + { + operator= (other); + } + + /** + * @brief Assignment + */ + TextsIterator &operator= (const TextsIterator &other) + { + if (this != &other) { + delete mp_delegate; + mp_delegate = other.mp_delegate ? other.mp_delegate->clone () : 0; + } + return *this; + } + + /** + * @Returns true, if the iterator is at the end + */ + bool at_end () const + { + return mp_delegate == 0 || mp_delegate->at_end (); + } + + /** + * @brief Increment + */ + TextsIterator &operator++ () + { + if (mp_delegate) { + mp_delegate->increment (); + } + return *this; + } + + /** + * @brief Access + */ + reference operator* () const + { + const value_type *value = operator-> (); + tl_assert (value != 0); + return *value; + } + + /** + * @brief Access + */ + pointer operator-> () const + { + return mp_delegate ? mp_delegate->get () : 0; + } + +private: + TextsIteratorDelegate *mp_delegate; +}; + +/** + * @brief A helper class allowing delivery of addressable texts + * + * In some applications (i.e. box scanner), texts need to be taken + * by address. The text set cannot always deliver adressable edges. + * This class help providing this ability by keeping a temporary copy + * if required. + */ + +class DB_PUBLIC AddressableTextDelivery +{ +public: + AddressableTextDelivery () + : m_iter (), m_valid (false) + { + // .. nothing yet .. + } + + AddressableTextDelivery (const TextsIterator &iter, bool valid) + : m_iter (iter), m_valid (valid) + { + if (! m_valid && ! m_iter.at_end ()) { + m_heap.push_back (*m_iter); + } + } + + bool at_end () const + { + return m_iter.at_end (); + } + + AddressableTextDelivery &operator++ () + { + ++m_iter; + if (! m_valid && ! m_iter.at_end ()) { + m_heap.push_back (*m_iter); + } + return *this; + } + + const db::Text *operator-> () const + { + if (m_valid) { + return m_iter.operator-> (); + } else { + return &m_heap.back (); + } + } + +private: + TextsIterator m_iter; + bool m_valid; + std::list m_heap; +}; + +class Texts; + +/** + * @brief A base class for text filters + */ +class DB_PUBLIC TextFilterBase +{ +public: + TextFilterBase () { } + virtual ~TextFilterBase () { } + + virtual bool selected (const db::Text &text) const = 0; + virtual const TransformationReducer *vars () const = 0; +}; + +/** + * @brief A set of texts + * + * Texts are convenient objects describing labels (a point and a text). + * + * Text sets are created from a text-delivering recursive shape iterator for example. Text sets + * can be converted to polygons (representing a small box around the text's point) or to dot-like + * edges representing the point of the text. + */ +class DB_PUBLIC Texts + : public gsi::ObjectBase +{ +public: + typedef db::Coord coord_type; + typedef db::coord_traits coord_traits; + typedef db::Text edge_pair_type; + typedef db::Vector vector_type; + typedef db::Point point_type; + typedef db::Box box_type; + typedef coord_traits::distance_type distance_type; + typedef TextsIterator const_iterator; + + /** + * @brief Default constructor + * + * This constructor creates an empty text set. + */ + Texts (); + + /** + * @brief Destructor + */ + ~Texts (); + + /** + * @brief Constructor from a delegate + * + * The region will take ownership of the delegate. + */ + Texts (TextsDelegate *delegate); + + /** + * @brief Copy constructor + */ + Texts (const Texts &other); + + /** + * @brief Assignment + */ + Texts &operator= (const Texts &other); + + /** + * @brief Constructor from an object + * + * Creates an text set representing a single instance of that object + */ + explicit Texts (const db::Text &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from an object + * + * Creates an text set representing a single instance of that object + */ + explicit Texts (const db::Shape &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Sequence constructor + * + * Creates an edge set from a sequence of objects. The objects need to be texts. + * This version accepts iterators of the begin ... end style. + */ + template + explicit Texts (const Iter &b, const Iter &e) + : mp_delegate (0) + { + reserve (e - b); + for (Iter i = b; i != e; ++i) { + insert (*i); + } + } + + /** + * @brief Constructor from a RecursiveShapeIterator + * + * Creates an text set from a recursive shape iterator. This allows one to feed an text set + * from a hierarchy of cells. + */ + explicit Texts (const RecursiveShapeIterator &si); + + /** + * @brief Constructor from a RecursiveShapeIterator with a transformation + * + * Creates an text set from a recursive shape iterator. This allows one to feed an text set + * from a hierarchy of cells. The transformation is useful to scale to a specific + * DBU for example. + */ + explicit Texts (const RecursiveShapeIterator &si, const db::ICplxTrans &trans); + + /** + * @brief Constructor from a RecursiveShapeIterator providing a deep representation + * + * This version will create a hierarchical text collection. The DeepShapeStore needs to be provided + * during the lifetime of the collection and acts as a heap for optimized data. + */ + explicit Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss); + + /** + * @brief Constructor from a RecursiveShapeIterator providing a deep representation with transformation + */ + explicit Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans); + + /** + * @brief Gets the underlying delegate object + */ + TextsDelegate *delegate () const + { + return mp_delegate; + } + + /** + * @brief Iterator of the text set + * + * The iterator delivers the edges of the text set. + * It follows the at_end semantics. + */ + const_iterator begin () const + { + return TextsIterator (mp_delegate->begin ()); + } + + /** + * @brief Delivers a RecursiveShapeIterator pointing to the texts plus the necessary transformation + */ + std::pair begin_iter () const + { + return mp_delegate->begin_iter (); + } + + /** + * @brief Inserts the given shape (working object) into the text set + */ + template + void insert (const Sh &shape); + + /** + * @brief Insert a shape reference into the text set + */ + void insert (const db::Shape &shape); + + /** + * @brief Insert a transformed shape into the text set + */ + template + void insert (const db::Shape &shape, const T &trans); + + /** + * @brief Returns true if the edge pair set is empty + */ + bool empty () const + { + return mp_delegate->empty (); + } + + /** + * @brief Returns the number of texts in the text set + */ + size_t size () const + { + return mp_delegate->size (); + } + + /** + * @brief Returns a string representing the text set + * + * nmax specifies how many texts are included (set to std::numeric_limits::max() for "all". + */ + std::string to_string (size_t nmax = 10) const + { + return mp_delegate->to_string (nmax); + } + + /** + * @brief Clears the text set + */ + void clear (); + + /** + * @brief Reserve memory for the given number of texts + */ + void reserve (size_t n); + + /** + * @brief Returns the bounding box of the text set + */ + Box bbox () const + { + return mp_delegate->bbox (); + } + + /** + * @brief Filters the texts + * + * This method will keep all texts for which the filter returns true. + */ + Texts &filter (const TextFilterBase &filter) + { + set_delegate (mp_delegate->filter_in_place (filter)); + return *this; + } + + /** + * @brief Returns the filtered texts + * + * This method will return a new text set with only those texts which + * conform to the filter criterion. + */ + Texts filtered (const TextFilterBase &filter) const + { + return Texts (mp_delegate->filtered (filter)); + } + + /** + * @brief Transforms the text set + */ + template + Texts &transform (const T &trans); + + /** + * @brief Returns the transformed text set + */ + template + Texts transformed (const T &trans) const + { + Texts d (*this); + d.transform (trans); + return d; + } + + /** + * @brief Swaps with the other text set + */ + void swap (db::Texts &other) + { + std::swap (other.mp_delegate, mp_delegate); + } + + /** + * @brief Joining of text set + * + * This method joins the text sets. + */ + Texts operator+ (const Texts &other) const + { + return Texts (mp_delegate->add (other)); + } + + /** + * @brief In-place text set joining + */ + Texts &operator+= (const Texts &other) + { + set_delegate (mp_delegate->add_in_place (other)); + return *this; + } + + /** + * @brief Returns all texts which are in the other text set + * + * This method will return all texts which are part of another text set. + * The match is done exactly. + * The "invert" flag can be used to invert the sense, i.e. with + * "invert" set to true, this method will return all texts not + * in the other text set. + */ + Texts in (const Texts &other, bool invert = false) const + { + return Texts (mp_delegate->in (other, invert)); + } + + /** + * @brief Returns the nth text + * + * This operation is available only for flat regions - i.e. such for which + * "has_valid_texts" is true. + */ + const db::Text *nth (size_t n) const + { + return mp_delegate->nth (n); + } + + /** + * @brief Forces flattening of the text collection + * + * This method will turn any edge pair collection into a flat one. + */ + void flatten () + { + flat_texts (); + } + + /** + * @brief Returns true, if the text set has valid texts stored within itself + * + * If the region has valid texts, it is permissable to use the text's addresses + * from the iterator. Furthermore, the random access operator nth() is available. + */ + bool has_valid_texts () const + { + return mp_delegate->has_valid_texts (); + } + + /** + * @brief Returns an addressable delivery for texts + * + * This object allows accessing the texts by address, even if they + * are not delivered from a container. The magic is a heap object + * inside the delivery object. Hence, the deliver object must persist + * as long as the addresses are required. + */ + AddressableTextDelivery addressable_texts () const + { + return AddressableTextDelivery (begin (), has_valid_texts ()); + } + + /** + * @brief Gets the internal iterator + * + * This method is intended for users who know what they are doing + */ + const db::RecursiveShapeIterator &iter () const; + + /** + * @brief Equality + */ + bool operator== (const db::Texts &other) const + { + return mp_delegate->equals (other); + } + + /** + * @brief Inequality + */ + bool operator!= (const db::Texts &other) const + { + return ! mp_delegate->equals (other); + } + + /** + * @brief Less operator + */ + bool operator< (const db::Texts &other) const + { + return mp_delegate->less (other); + } + + /** + * @brief Converts to polygons + * + * Note: because of the include hierarchy we can't use a direct return value. + * + * The output container is not cleared by this method but polygons are rather + * appended. + * + * The given extension is applied in all directions rendering a square of 2*e + * width and height. The center of the boxes will be the position of the texts. + */ + void polygons (Region &output, db::Coord e = 1) const; + + /** + * @brief Returns individual, dot-like edges + * + * Note: because of the include hierarchy we can't use a direct return value. + * + * The returned edges will be dot-like (identical points) and represent the + * position of the text. + */ + void edges (Edges &output) const; + + /** + * @brief Enable progress reporting + * + * @param progress_text The description text of the progress object + */ + void enable_progress (const std::string &progress_desc = std::string ()) + { + mp_delegate->enable_progress (progress_desc); + } + + /** + * @brief Disable progress reporting + */ + void disable_progress () + { + mp_delegate->disable_progress (); + } + + /** + * @brief Inserts the edge pair collection into the given layout, cell and layer + * If the text collection is a hierarchical region, the hierarchy is copied into the + * layout's hierarchy. + */ + void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const + { + return mp_delegate->insert_into (layout, into_cell, into_layer); + } + + /** + * @brief Inserts the edge pair collection into the given layout, cell and layer as polygons with the given enlargement + * If the text collection is a hierarchical region, the hierarchy is copied into the + * layout's hierarchy. + */ + void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const + { + return mp_delegate->insert_into_as_polygons (layout, into_cell, into_layer, enl); + } + +private: + TextsDelegate *mp_delegate; + + void set_delegate (TextsDelegate *delegate); + FlatTexts *flat_texts (); +}; + +} + +namespace tl +{ + /** + * @brief The type traits for the box type + */ + template <> + struct type_traits : public type_traits + { + typedef true_tag supports_extractor; + typedef true_tag supports_to_string; + typedef true_tag has_less_operator; + typedef true_tag has_equal_operator; + }; + +} + +#endif + diff --git a/src/db/db/dbTextsDelegate.cc b/src/db/db/dbTextsDelegate.cc new file mode 100644 index 000000000..0691920f4 --- /dev/null +++ b/src/db/db/dbTextsDelegate.cc @@ -0,0 +1,68 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbTextsDelegate.h" + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- + +TextsDelegate::TextsDelegate () +{ + m_report_progress = false; +} + +TextsDelegate::TextsDelegate (const TextsDelegate &other) + : tl::UniqueId () +{ + operator= (other); +} + +TextsDelegate & +TextsDelegate::operator= (const TextsDelegate &other) +{ + if (this != &other) { + m_report_progress = other.m_report_progress; + } + return *this; +} + +TextsDelegate::~TextsDelegate () +{ + // .. nothing yet .. +} + +void TextsDelegate::enable_progress (const std::string &progress_desc) +{ + m_report_progress = true; + m_progress_desc = progress_desc; +} + +void TextsDelegate::disable_progress () +{ + m_report_progress = false; +} + +} + diff --git a/src/db/db/dbTextsDelegate.h b/src/db/db/dbTextsDelegate.h new file mode 100644 index 000000000..d25eef6a3 --- /dev/null +++ b/src/db/db/dbTextsDelegate.h @@ -0,0 +1,140 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbTextsDelegate +#define HDR_dbTextsDelegate + +#include "dbCommon.h" + +#include "dbText.h" +#include "tlUniqueId.h" + +namespace db { + +class RecursiveShapeIterator; +class Texts; +class TextFilterBase; +class RegionDelegate; +class EdgesDelegate; +class Layout; + +/** + * @brief The edge pair set iterator delegate + */ +class DB_PUBLIC TextsIteratorDelegate +{ +public: + TextsIteratorDelegate () { } + virtual ~TextsIteratorDelegate () { } + + typedef db::Text value_type; + + virtual bool at_end () const = 0; + virtual void increment () = 0; + virtual const value_type *get () const = 0; + virtual TextsIteratorDelegate *clone () const = 0; +}; + +/** + * @brief The delegate for the actual edge set implementation + */ +class DB_PUBLIC TextsDelegate + : public tl::UniqueId +{ +public: + typedef db::Coord coord_type; + typedef db::coord_traits coord_traits; + typedef db::Text edge_pair_type; + typedef db::Vector vector_type; + typedef db::Point point_type; + typedef db::Box box_type; + + TextsDelegate (); + virtual ~TextsDelegate (); + + TextsDelegate (const TextsDelegate &other); + TextsDelegate &operator= (const TextsDelegate &other); + + virtual TextsDelegate *clone () const = 0; + + void enable_progress (const std::string &progress_desc); + void disable_progress (); + + // dummy features to harmonize the interface of region, edges and edge pair delegates + void set_merged_semantics (bool) { } + bool merged_semantics () const { return false; } + void set_is_merged (bool) { } + bool is_merged () const { return false; } + + virtual std::string to_string (size_t nmax) const = 0; + + virtual TextsIteratorDelegate *begin () const = 0; + virtual std::pair begin_iter () const = 0; + + virtual bool empty () const = 0; + virtual size_t size () const = 0; + + virtual Box bbox () const = 0; + + virtual TextsDelegate *filter_in_place (const TextFilterBase &filter) = 0; + virtual TextsDelegate *filtered (const TextFilterBase &filter) const = 0; + + virtual RegionDelegate *polygons (db::Coord e) const = 0; + virtual EdgesDelegate *edges () const = 0; + + virtual TextsDelegate *add_in_place (const Texts &other) = 0; + virtual TextsDelegate *add (const Texts &other) const = 0; + + virtual TextsDelegate *in (const Texts &other, bool invert) const = 0; + + virtual const db::Text *nth (size_t n) const = 0; + virtual bool has_valid_texts () const = 0; + + virtual const db::RecursiveShapeIterator *iter () const = 0; + + virtual bool equals (const Texts &other) const = 0; + virtual bool less (const Texts &other) const = 0; + + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0; + virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const = 0; + +protected: + const std::string &progress_desc () const + { + return m_progress_desc; + } + + bool report_progress () const + { + return m_report_progress; + } + +private: + bool m_report_progress; + std::string m_progress_desc; +}; + +} + +#endif + diff --git a/src/db/db/dbTextsUtils.cc b/src/db/db/dbTextsUtils.cc new file mode 100644 index 000000000..9c39d3e05 --- /dev/null +++ b/src/db/db/dbTextsUtils.cc @@ -0,0 +1,31 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbTextsUtils.h" +#include "dbRegion.h" + +namespace db +{ + + // .. nothing yet .. + +} diff --git a/src/db/db/dbTextsUtils.h b/src/db/db/dbTextsUtils.h new file mode 100644 index 000000000..5b604f89f --- /dev/null +++ b/src/db/db/dbTextsUtils.h @@ -0,0 +1,154 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_dbTextsUtils +#define HDR_dbTextsUtils + +#include "dbCommon.h" +#include "dbTexts.h" +#include "tlGlobPattern.h" + +namespace db { + +/** + * @brief An text filter filtering by a string + * + * It will filter all texts for which the string is equal to "text". + * There is an "invert" flag which allows selecting all texts not + * matching the criterion. + */ + +struct DB_PUBLIC TextStringFilter + : public TextFilterBase +{ + /** + * @brief Constructor + * + * @param text The text string to match + * @param inverse If set to true, only polygons not matching this criterion will be filtered + */ + TextStringFilter (const std::string &text, bool inverse) + : m_text (text), m_inverse (inverse) + { + // .. nothing yet .. + } + + /** + * @brief Returns true if the text matches the criterion + */ + virtual bool selected (const db::Text &text) const + { + return (text.string () == m_text) != m_inverse; + } + + /** + * @brief This filter is not sensitive to hierarchy + */ + virtual const TransformationReducer *vars () const + { + return 0; + } + + /** + * @brief Requires merged input + */ + virtual bool requires_raw_input () const + { + return false; + } + + /** + * @brief Wants to build variants + */ + virtual bool wants_variants () const + { + return false; + } + +private: + std::string m_text; + bool m_inverse; +}; + +/** + * @brief An text filter filtering by a glob-style pattern + * + * It will filter all texts for which the string matches the given glob-style pattern. + * There is an "invert" flag which allows selecting all texts not + * matching the criterion. + */ + +struct DB_PUBLIC TextPatternFilter + : public TextFilterBase +{ + /** + * @brief Constructor + * + * @param text The text pattern to match + * @param inverse If set to true, only polygons not matching this criterion will be filtered + */ + TextPatternFilter (const std::string &text, bool inverse) + : m_pattern (text), m_inverse (inverse) + { + // .. nothing yet .. + } + + /** + * @brief Returns true if the text matches the criterion + */ + virtual bool selected (const db::Text &text) const + { + return m_pattern.match (text.string ()) != m_inverse; + } + + /** + * @brief This filter is not sensitive to hierarchy + */ + virtual const TransformationReducer *vars () const + { + return 0; + } + + /** + * @brief Requires merged input + */ + virtual bool requires_raw_input () const + { + return false; + } + + /** + * @brief Wants to build variants + */ + virtual bool wants_variants () const + { + return false; + } + +private: + tl::GlobPattern m_pattern; + bool m_inverse; +}; + +} // namespace db + +#endif diff --git a/src/db/db/gsiDeclDbTexts.cc b/src/db/db/gsiDeclDbTexts.cc new file mode 100644 index 000000000..c701d2a1a --- /dev/null +++ b/src/db/db/gsiDeclDbTexts.cc @@ -0,0 +1,470 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "gsiDecl.h" + +#include "dbTexts.h" +#include "dbRegion.h" +#include "dbDeepTexts.h" +#include "dbTextsUtils.h" + +namespace gsi +{ + +static db::Texts *new_v () +{ + return new db::Texts (); +} + +static db::Texts *new_a (const std::vector &t) +{ + return new db::Texts (t.begin (), t.end ()); +} + +static db::Texts *new_text (const db::Text &t) +{ + return new db::Texts (t); +} + +static db::Texts *new_shapes (const db::Shapes &s) +{ + db::Texts *r = new db::Texts (); + for (db::Shapes::shape_iterator i = s.begin (db::ShapeIterator::Texts); !i.at_end (); ++i) { + r->insert (*i); + } + return r; +} + +static db::Texts *new_si (const db::RecursiveShapeIterator &si) +{ + return new db::Texts (si); +} + +static db::Texts *new_si2 (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans) +{ + return new db::Texts (si, trans); +} + +static db::Texts *new_sid (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss) +{ + return new db::Texts (si, dss); +} + +static db::Texts *new_si2d (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const db::ICplxTrans &trans) +{ + return new db::Texts (si, dss, trans); +} + +static std::string to_string0 (const db::Texts *r) +{ + return r->to_string (); +} + +static std::string to_string1 (const db::Texts *r, size_t n) +{ + return r->to_string (n); +} + +static db::Texts &move_p (db::Texts *r, const db::Vector &p) +{ + r->transform (db::Disp (p)); + return *r; +} + +static db::Texts &move_xy (db::Texts *r, db::Coord x, db::Coord y) +{ + r->transform (db::Disp (db::Vector (x, y))); + return *r; +} + +static db::Texts moved_p (const db::Texts *r, const db::Vector &p) +{ + return r->transformed (db::Disp (p)); +} + +static db::Texts moved_xy (const db::Texts *r, db::Coord x, db::Coord y) +{ + return r->transformed (db::Disp (db::Vector (x, y))); +} + +static db::Region polygons0 (const db::Texts *e, db::Coord d) +{ + db::Region r; + e->polygons (r, d); + return r; +} + +static db::Region extents1 (const db::Texts *r, db::Coord dx, db::Coord dy) +{ + db::Region e; + e.reserve (r->size ()); + for (db::Texts::const_iterator i = r->begin (); ! i.at_end (); ++i) { + e.insert (i->box ().enlarged (db::Vector (dx, dy))); + } + return e; +} + +static db::Region extents0 (const db::Texts *r, db::Coord d) +{ + return extents1 (r, d, d); +} + +static db::Edges edges (const db::Texts *ep) +{ + db::Edges e; + ep->edges (e); + return e; +} + +static void insert_t (db::Texts *t, const db::Texts &a) +{ + for (db::Texts::const_iterator p = a.begin (); ! p.at_end (); ++p) { + t->insert (*p); + } +} + +static bool is_deep (const db::Texts *t) +{ + return dynamic_cast (t->delegate ()) != 0; +} + +static size_t id (const db::Texts *t) +{ + return tl::id_of (t->delegate ()); +} + +static db::Texts with_text (const db::Texts *r, const std::string &text, bool inverse) +{ + db::TextStringFilter f (text, inverse); + return r->filtered (f); +} + +static db::Texts with_pattern (const db::Texts *r, const std::string &pattern, bool inverse) +{ + db::TextPatternFilter f (pattern, inverse); + return r->filtered (f); +} + +Class decl_Texts ("db", "Texts", + constructor ("new", &new_v, + "@brief Default constructor\n" + "\n" + "This constructor creates an empty text collection.\n" + ) + + constructor ("new", &new_a, gsi::arg ("array"), + "@brief Constructor from an text array\n" + "\n" + "This constructor creates an text collection from an array of \\Text objects.\n" + ) + + constructor ("new", &new_text, gsi::arg ("text"), + "@brief Constructor from a single edge pair object\n" + "\n" + "This constructor creates an text collection with a single text.\n" + ) + + constructor ("new", &new_shapes, gsi::arg ("shapes"), + "@brief Shapes constructor\n" + "\n" + "This constructor creates an text collection from a \\Shapes collection.\n" + ) + + constructor ("new", &new_si, gsi::arg ("shape_iterator"), + "@brief Constructor from a hierarchical shape set\n" + "\n" + "This constructor creates a text collection from the shapes delivered by the given recursive shape iterator.\n" + "Only texts are taken from the shape set and other shapes are ignored.\n" + "This method allows feeding the text collection from a hierarchy of cells.\n" + "\n" + "@code\n" + "layout = ... # a layout\n" + "cell = ... # the index of the initial cell\n" + "layer = ... # the index of the layer from where to take the shapes from\n" + "r = RBA::Texts::new(layout.begin_shapes(cell, layer))\n" + "@/code\n" + ) + + constructor ("new", &new_si2, gsi::arg ("shape_iterator"), gsi::arg ("trans"), + "@brief Constructor from a hierarchical shape set with a transformation\n" + "\n" + "This constructor creates a text collection from the shapes delivered by the given recursive shape iterator.\n" + "Only texts are taken from the shape set and other shapes are ignored.\n" + "The given transformation is applied to each text taken.\n" + "This method allows feeding the text collection from a hierarchy of cells.\n" + "The transformation is useful to scale to a specific database unit for example.\n" + "\n" + "@code\n" + "layout = ... # a layout\n" + "cell = ... # the index of the initial cell\n" + "layer = ... # the index of the layer from where to take the shapes from\n" + "dbu = 0.1 # the target database unit\n" + "r = RBA::Texts::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n" + "@/code\n" + ) + + constructor ("new", &new_sid, gsi::arg ("shape_iterator"), gsi::arg ("dss"), + "@brief Creates a hierarchical text collection from an original layer\n" + "\n" + "This constructor creates a text collection from the shapes delivered by the given recursive shape iterator.\n" + "This version will create a hierarchical text collection which supports hierarchical operations.\n" + "\n" + "@code\n" + "dss = RBA::DeepShapeStore::new\n" + "layout = ... # a layout\n" + "cell = ... # the index of the initial cell\n" + "layer = ... # the index of the layer from where to take the shapes from\n" + "r = RBA::Texts::new(layout.begin_shapes(cell, layer))\n" + "@/code\n" + ) + + constructor ("new", &new_si2d, gsi::arg ("shape_iterator"), gsi::arg ("dss"), gsi::arg ("trans"), + "@brief Creates a hierarchical text collection from an original layer with a transformation\n" + "\n" + "This constructor creates a text collection from the shapes delivered by the given recursive shape iterator.\n" + "This version will create a hierarchical text collection which supports hierarchical operations.\n" + "The transformation is useful to scale to a specific database unit for example.\n" + "\n" + "@code\n" + "dss = RBA::DeepShapeStore::new\n" + "layout = ... # a layout\n" + "cell = ... # the index of the initial cell\n" + "layer = ... # the index of the layer from where to take the shapes from\n" + "dbu = 0.1 # the target database unit\n" + "r = RBA::Texts::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n" + "@/code\n" + ) + + method ("insert_into", &db::Texts::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"), + "@brief Inserts this texts into the given layout, below the given cell and into the given layer.\n" + "If the text collection is a hierarchical one, a suitable hierarchy will be built below the top cell or " + "and existing hierarchy will be reused.\n" + ) + + method ("insert_into_as_polygons", &db::Texts::insert_into_as_polygons, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("e"), + "@brief Inserts this texts into the given layout, below the given cell and into the given layer.\n" + "If the text collection is a hierarchical one, a suitable hierarchy will be built below the top cell or " + "and existing hierarchy will be reused.\n" + "\n" + "The texts will be converted to polygons with the enlargement value given be 'e'. See \\polygon or \\extents for details.\n" + ) + + method ("insert", (void (db::Texts::*) (const db::Text &)) &db::Texts::insert, gsi::arg ("text"), + "@brief Inserts a text into the collection\n" + ) + + method_ext ("is_deep?", &is_deep, + "@brief Returns true if the edge pair collection is a deep (hierarchical) one\n" + ) + + method_ext ("data_id", &id, + "@brief Returns the data ID (a unique identifier for the underlying data storage)\n" + ) + + method ("+", &db::Texts::operator+, gsi::arg ("other"), + "@brief Returns the combined text collection of self and the other one\n" + "\n" + "@return The resulting text collection\n" + "\n" + "This operator adds the texts of the other collection to self and returns a new combined set.\n" + ) + + method ("+=", &db::Texts::operator+=, gsi::arg ("other"), + "@brief Adds the texts of the other text collection to self\n" + "\n" + "@return The text collection after modification (self)\n" + "\n" + "This operator adds the texts of the other collection to self.\n" + ) + + method_ext ("move", &move_p, gsi::arg ("p"), + "@brief Moves the text collection\n" + "\n" + "Moves the texts by the given offset and returns the \n" + "moved text collection. The text collection is overwritten.\n" + "\n" + "@param p The distance to move the texts.\n" + "\n" + "@return The moved texts (self).\n" + ) + + method_ext ("move", &move_xy, gsi::arg ("x"), gsi::arg ("y"), + "@brief Moves the text collection\n" + "\n" + "Moves the edge pairs by the given offset and returns the \n" + "moved texts. The edge pair collection is overwritten.\n" + "\n" + "@param x The x distance to move the texts.\n" + "@param y The y distance to move the texts.\n" + "\n" + "@return The moved texts (self).\n" + ) + + method_ext ("moved", &moved_p, gsi::arg ("p"), + "@brief Returns the moved text collection (does not modify self)\n" + "\n" + "Moves the texts by the given offset and returns the \n" + "moved texts. The text collection is not modified.\n" + "\n" + "@param p The distance to move the texts.\n" + "\n" + "@return The moved texts.\n" + ) + + method_ext ("moved", &moved_xy, gsi::arg ("x"), gsi::arg ("y"), + "@brief Returns the moved edge pair collection (does not modify self)\n" + "\n" + "Moves the texts by the given offset and returns the \n" + "moved texts. The text collection is not modified.\n" + "\n" + "@param x The x distance to move the texts.\n" + "@param y The y distance to move the texts.\n" + "\n" + "@return The moved texts.\n" + ) + + method ("transformed", (db::Texts (db::Texts::*)(const db::Trans &) const) &db::Texts::transformed, gsi::arg ("t"), + "@brief Transform the edge pair collection\n" + "\n" + "Transforms the texts with the given transformation.\n" + "Does not modify the edge pair collection but returns the transformed texts.\n" + "\n" + "@param t The transformation to apply.\n" + "\n" + "@return The transformed texts.\n" + ) + + method ("transformed|#transformed_icplx", (db::Texts (db::Texts::*)(const db::ICplxTrans &) const) &db::Texts::transformed, gsi::arg ("t"), + "@brief Transform the text collection with a complex transformation\n" + "\n" + "Transforms the text with the given complex transformation.\n" + "Does not modify the text collection but returns the transformed texts.\n" + "\n" + "@param t The transformation to apply.\n" + "\n" + "@return The transformed texts.\n" + ) + + method ("transform", (db::Texts &(db::Texts::*)(const db::Trans &)) &db::Texts::transform, gsi::arg ("t"), + "@brief Transform the text collection (modifies self)\n" + "\n" + "Transforms the text collection with the given transformation.\n" + "This version modifies the text collection and returns a reference to self.\n" + "\n" + "@param t The transformation to apply.\n" + "\n" + "@return The transformed text collection.\n" + ) + + method ("transform|#transform_icplx", (db::Texts &(db::Texts::*)(const db::ICplxTrans &)) &db::Texts::transform, gsi::arg ("t"), + "@brief Transform the text collection with a complex transformation (modifies self)\n" + "\n" + "Transforms the text collection with the given transformation.\n" + "This version modifies the text collection and returns a reference to self.\n" + "\n" + "@param t The transformation to apply.\n" + "\n" + "@return The transformed text collection.\n" + ) + + method_ext ("insert", &insert_t, gsi::arg ("texts"), + "@brief Inserts all texts from the other text collection into this collection\n" + ) + + method_ext ("edges", &edges, + "@brief Returns dot-like edges for the texts\n" + "@return An edge collection containing the individual, dot-like edges\n" + ) + + method_ext ("extents", &extents0, gsi::arg ("d", db::Coord (1)), + "@brief Returns a region with the enlarged bounding boxes of the texts\n" + "Text bounding boxes are point-like boxes which vanish unless an enlargement of >0 is specified.\n" + "The bounding box is centered at the text's location.\n" + "The boxes will not be merged, so it is possible to determine overlaps " + "of these boxes for example.\n" + ) + + method_ext ("extents", &extents1, gsi::arg ("dx"), gsi::arg ("dy"), + "@brief Returns a region with the enlarged bounding boxes of the texts\n" + "This method acts like the other version of \\extents, but allows giving different enlargements for x and y direction.\n" + ) + + method_ext ("polygons", &polygons0, gsi::arg ("e", db::Coord (1)), + "@brief Converts the edge pairs to polygons\n" + "This method creates polygons from the texts. This is equivalent to calling \\extents." + ) + + method_ext ("with_text", with_text, gsi::arg ("text"), gsi::arg ("inverse"), + "@brief Filter the text by text string\n" + "If \"inverse\" is false, this method returns the texts with the given string.\n" + "If \"inverse\" is true, this method returns the texts not having the given string.\n" + ) + + method_ext ("with_match", with_pattern, gsi::arg ("pattern"), gsi::arg ("inverse"), + "@brief Filter the text by glob pattern\n" + "\"pattern\" is a glob-style pattern (e.g. \"A*\" will select all texts starting with a capital \"A\").\n" + "If \"inverse\" is false, this method returns the texts matching the pattern.\n" + "If \"inverse\" is true, this method returns the texts not matching the pattern.\n" + ) + + method ("clear", &db::Texts::clear, + "@brief Clears the text collection\n" + ) + + method ("swap", &db::Texts::swap, gsi::arg ("other"), + "@brief Swap the contents of this collection with the contents of another collection\n" + "This method is useful to avoid excessive memory allocation in some cases. " + "For managed memory languages such as Ruby, those cases will be rare. " + ) + + method ("bbox", &db::Texts::bbox, + "@brief Return the bounding box of the text collection\n" + "The bounding box is the box enclosing all origins of all texts.\n" + ) + + method ("is_empty?", &db::Texts::empty, + "@brief Returns true if the collection is empty\n" + ) + + method ("size", &db::Texts::size, + "@brief Returns the number of texts in this collection\n" + ) + + gsi::iterator ("each", &db::Texts::begin, + "@brief Returns each text of the text collection\n" + ) + + method ("[]", &db::Texts::nth, gsi::arg ("n"), + "@brief Returns the nth text\n" + "\n" + "This method returns nil if the index is out of range. It is available for flat texts only - i.e. " + "those for which \\has_valid_texts? is true. Use \\flatten to explicitly flatten an text collection.\n" + "\n" + "The \\each iterator is the more general approach to access the texts." + ) + + method ("flatten", &db::Texts::flatten, + "@brief Explicitly flattens an text collection\n" + "\n" + "If the collection is already flat (i.e. \\has_valid_texts? returns true), this method will " + "not change the collection.\n" + ) + + method ("has_valid_texts?", &db::Texts::has_valid_texts, + "@brief Returns true if the text collection is flat and individual texts can be accessed randomly\n" + ) + + method ("enable_progress", &db::Texts::enable_progress, gsi::arg ("label"), + "@brief Enable progress reporting\n" + "After calling this method, the text collection will report the progress through a progress bar while " + "expensive operations are running.\n" + "The label is a text which is put in front of the progress bar.\n" + "Using a progress bar will imply a performance penalty of a few percent typically.\n" + ) + + method ("disable_progress", &db::Texts::disable_progress, + "@brief Disable progress reporting\n" + "Calling this method will disable progress reporting. See \\enable_progress.\n" + ) + + method_ext ("to_s", &to_string0, + "@brief Converts the text collection to a string\n" + "The length of the output is limited to 20 edge pairs to avoid giant strings on large collections. " + "For full output use \"to_s\" with a maximum count parameter.\n" + ) + + method_ext ("to_s", &to_string1, gsi::arg ("max_count"), + "@brief Converts the text collection to a string\n" + "This version allows specification of the maximum number of texts contained in the string." + ), + "@brief Texts (a collection of texts)\n" + "\n" + "Text objects are useful as labels for net names, to identify certain regions and to specify specific locations in general. " + "Text collections provide a way to store - also in a hierarchical fashion - and manipulate collection of text objects. " + "Text objects can be turned into polygons by creating small boxes around the texts. Texts can also be turned into dot-like " + "edges. Texts can be filtered by string, either by matching against a fixed string or a glob-style pattern.\n" + "\n" + "Beside that, text collections can be transformed and combined, similar to \\EdgePairs.\n" + "\n" + "This class has been introduced in version 0.27.\n" +); + +}