First implementation of texts collection.

This commit is contained in:
Matthias Koefferlein 2020-05-12 20:44:39 +02:00
parent 3f8090b3fd
commit a9cd9ac122
24 changed files with 3424 additions and 53 deletions

View File

@ -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") {

View File

@ -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 <sstream>
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 <db::Text> op;
for (TextsIterator o (other.begin ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::auto_ptr<FlatTexts> 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<FlatTexts> 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<FlatRegion> 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<FlatEdges> 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<FlatTexts *> (other.delegate ());
if (other_flat) {
std::auto_ptr<FlatTexts> 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<FlatTexts> 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));
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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
*

316
src/db/db/dbDeepTexts.cc Normal file
View File

@ -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 <sstream>
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<db::RecursiveShapeIterator, db::ICplxTrans> 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 <const DeepTexts *> (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<DeepTexts *> (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<db::Layout &> (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<db::Layout &> (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<const DeepTexts *> (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<const DeepTexts *> (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);
}
}

102
src/db/db/dbDeepTexts.h Normal file
View File

@ -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<db::RecursiveShapeIterator, db::ICplxTrans> 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

View File

@ -1301,6 +1301,7 @@ public:
private:
friend class EdgePairs;
friend class Texts;
EdgesDelegate *mp_delegate;

88
src/db/db/dbEmptyTexts.cc Normal file
View File

@ -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;
}
}

85
src/db/db/dbEmptyTexts.h Normal file
View File

@ -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<db::RecursiveShapeIterator, db::ICplxTrans> 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

220
src/db/db/dbFlatTexts.cc Normal file
View File

@ -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<db::Text, db::unstable_layer_tag> ().begin (), m_texts.get_layer<db::Text, db::unstable_layer_tag> ().end ());
}
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> 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<db::Text, db::unstable_layer_tag> ().begin ();
for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (pw == m_texts.get_layer<db::Text, db::unstable_layer_tag> ().end ()) {
m_texts.get_layer<db::Text, db::unstable_layer_tag> ().insert (*p);
pw = m_texts.get_layer<db::Text, db::unstable_layer_tag> ().end ();
} else {
m_texts.get_layer<db::Text, db::unstable_layer_tag> ().replace (pw++, *p);
}
}
}
m_texts.get_layer<db::Text, db::unstable_layer_tag> ().erase (pw, m_texts.get_layer<db::Text, db::unstable_layer_tag> ().end ());
return this;
}
TextsDelegate *FlatTexts::add (const Texts &other) const
{
std::auto_ptr<FlatTexts> new_texts (new FlatTexts (*this));
new_texts->invalidate_cache ();
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
if (other_flat) {
new_texts->raw_texts ().insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().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<FlatTexts *> (other.delegate ());
if (other_flat) {
m_texts.insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().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<db::Text, db::unstable_layer_tag> ().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);
}
}
}

171
src/db/db/dbFlatTexts.h Normal file
View File

@ -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<db::Text, db::unstable_layer_tag> 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<db::Text, db::unstable_layer_tag> 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<db::RecursiveShapeIterator, db::ICplxTrans> 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 <class T>
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 <class Iter>
void insert_seq (const Iter &seq)
{
for (Iter i = seq; ! i.at_end (); ++i) {
insert (*i);
}
}
template <class Trans>
void transform (const Trans &trans)
{
if (! trans.is_unity ()) {
for (text_iterator_type p = m_texts.template get_layer<db::Text, db::unstable_layer_tag> ().begin (); p != m_texts.template get_layer<db::Text, db::unstable_layer_tag> ().end (); ++p) {
m_texts.get_layer<db::Text, db::unstable_layer_tag> ().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

View File

@ -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));
}
}
}

View File

@ -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
*

View File

@ -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<db::RecursiveShapeIterator, db::ICplxTrans>
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<const OriginalLayerTexts *> (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<const OriginalLayerTexts *> (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 ..
}
}

View File

@ -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<db::RecursiveShapeIterator, db::ICplxTrans> 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

View File

@ -1612,6 +1612,7 @@ public:
private:
friend class Edges;
friend class EdgePairs;
friend class Texts;
RegionDelegate *mp_delegate;

207
src/db/db/dbTexts.cc Normal file
View File

@ -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 <sstream>
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 <class Sh>
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 <class T>
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 <class T>
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<FlatTexts *> (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")));
}
}
}

670
src/db/db/dbTexts.h Normal file
View File

@ -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 <list>
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<db::Text> 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<db::Coord> 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 <class Iter>
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<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const
{
return mp_delegate->begin_iter ();
}
/**
* @brief Inserts the given shape (working object) into the text set
*/
template <class Sh>
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 <class T>
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<size_t>::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 <class T>
Texts &transform (const T &trans);
/**
* @brief Returns the transformed text set
*/
template <class T>
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 <db::Texts> : public type_traits<void>
{
typedef true_tag supports_extractor;
typedef true_tag supports_to_string;
typedef true_tag has_less_operator;
typedef true_tag has_equal_operator;
};
}
#endif

View File

@ -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;
}
}

140
src/db/db/dbTextsDelegate.h Normal file
View File

@ -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<db::Coord> 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<db::RecursiveShapeIterator, db::ICplxTrans> 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

31
src/db/db/dbTextsUtils.cc Normal file
View File

@ -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 ..
}

154
src/db/db/dbTextsUtils.h Normal file
View File

@ -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

470
src/db/db/gsiDeclDbTexts.cc Normal file
View File

@ -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<db::Text> &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<const db::DeepTexts *> (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<db::Texts> 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"
);
}