Merge remote-tracking branch 'origin/master' into master-mac-qt6

This commit is contained in:
Kazunari Sekigawa 2022-09-06 06:55:02 +09:00
commit 2c6f025b23
25 changed files with 486 additions and 180 deletions

View File

@ -30,34 +30,43 @@ namespace bd
{
GenericWriterOptions::GenericWriterOptions ()
: m_scale_factor (1.0),
m_dbu (0.0),
m_dont_write_empty_cells (false),
m_keep_instances (false),
m_write_context_info (true),
m_gds2_max_vertex_count (8000),
m_gds2_no_zero_length_paths (false),
m_gds2_multi_xy_records (false),
m_gds2_resolve_skew_arrays (false),
m_gds2_max_cellname_length (32000),
m_gds2_libname ("LIB"),
m_gds2_user_units (1.0),
m_gds2_write_timestamps (true),
m_gds2_write_cell_properties (false),
m_gds2_write_file_properties (false),
m_oasis_compression_level (2),
m_oasis_write_cblocks (false),
m_oasis_strict_mode (false),
m_oasis_recompress (false),
m_oasis_permissive (false),
m_oasis_write_std_properties (1),
m_oasis_subst_char ("*"),
m_cif_dummy_calls (false),
m_cif_blank_separator (false),
m_magic_lambda (1.0),
m_dxf_polygon_mode (0)
: m_scale_factor (1.0)
{
// .. nothing yet ..
db::SaveLayoutOptions save_options;
m_dbu = save_options.get_option_by_name ("dbu").to_double ();
m_dont_write_empty_cells = save_options.get_option_by_name ("no_empty_cells").to_bool ();
m_keep_instances = save_options.get_option_by_name ("keep_instances").to_bool ();
m_write_context_info = save_options.get_option_by_name ("write_context_info").to_bool ();
m_gds2_max_vertex_count = save_options.get_option_by_name ("gds2_max_vertex_count").to_uint ();
m_gds2_no_zero_length_paths = save_options.get_option_by_name ("gds2_no_zero_length_paths").to_bool ();
m_gds2_multi_xy_records = save_options.get_option_by_name ("gds2_multi_xy_records").to_bool ();
m_gds2_resolve_skew_arrays = save_options.get_option_by_name ("gds2_resolve_skew_arrays").to_bool ();
m_gds2_max_cellname_length = save_options.get_option_by_name ("gds2_max_cellname_length").to_uint ();
m_gds2_libname = save_options.get_option_by_name ("gds2_libname").to_string ();
m_gds2_user_units = save_options.get_option_by_name ("gds2_user_units").to_double ();
m_gds2_write_timestamps = save_options.get_option_by_name ("gds2_write_timestamps").to_bool ();
m_gds2_write_cell_properties = save_options.get_option_by_name ("gds2_write_cell_properties").to_bool ();
m_gds2_write_file_properties = save_options.get_option_by_name ("gds2_write_file_properties").to_bool ();
m_oasis_compression_level = save_options.get_option_by_name ("oasis_compression_level").to_int ();
m_oasis_write_cblocks = save_options.get_option_by_name ("oasis_write_cblocks").to_bool ();
m_oasis_strict_mode = save_options.get_option_by_name ("oasis_strict_mode").to_bool ();
m_oasis_recompress = save_options.get_option_by_name ("oasis_recompress").to_bool ();
m_oasis_permissive = save_options.get_option_by_name ("oasis_permissive").to_bool ();
m_oasis_write_std_properties = save_options.get_option_by_name ("oasis_write_std_properties").to_int ();
m_oasis_subst_char = save_options.get_option_by_name ("oasis_substitution_char").to_string ();
m_cif_dummy_calls = save_options.get_option_by_name ("cif_dummy_calls").to_bool ();
m_cif_blank_separator = save_options.get_option_by_name ("cif_blank_separator").to_bool ();
// The default options do not specify a lambda, but we prefer having a default here:
// m_magic_lambda = save_options.get_option_by_name ("mag_lambda").to_double ();
m_magic_lambda = 1.0;
m_dxf_polygon_mode = save_options.get_option_by_name ("dxf_polygon_mode").to_int ();
}
const std::string GenericWriterOptions::gds2_format_name = "GDS2";
@ -210,10 +219,14 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
"* 2++ - enhanced shape array search algorithm using 2nd and further neighbor distances as well\n"
)
<< tl::arg (group +
"-ob|--cblocks", &m_oasis_write_cblocks, "Uses CBLOCK compression"
"-ob|--cblocks", &m_oasis_write_cblocks, "Uses CBLOCK compression",
"Please note that since version 0.27.12, CBLOCK compression is enabled by default. If you do not want "
"CBLOCK compression, use '--cblocks=false'."
)
<< tl::arg (group +
"-ot|--strict-mode", &m_oasis_strict_mode, "Uses strict mode"
"-ot|--strict-mode", &m_oasis_strict_mode, "Uses strict mode",
"Please note that since version 0.27.12, strict mode is enabled by default. If you do not want "
"strict mode, use '--strict-mode=false'."
)
<< tl::arg (group +
"#--recompress", &m_oasis_recompress, "Compresses shape arrays again",

View File

@ -58,9 +58,9 @@ TEST(1)
"--write-cell-properties",
"--write-file-properties",
// OASIS
"-ob",
"-ob=false",
"-ok=9",
"-ot",
"-ot=false",
"--recompress",
"--subst-char=XY",
"--write-std-properties=2"
@ -85,9 +85,9 @@ TEST(1)
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("gds2_user_units").to_double ()), "1");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_cell_properties").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_file_properties").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_compression_level").to_int (), 2);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_recompress").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "*");
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_std_properties_ext").to_int (), 1);
@ -110,9 +110,9 @@ TEST(1)
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("gds2_user_units").to_double ()), "2.5");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_cell_properties").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_file_properties").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_compression_level").to_int (), 9);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_recompress").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "X");
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_std_properties_ext").to_int (), 2);

View File

@ -78,11 +78,11 @@ LayoutStateModel::invalidate_bboxes (unsigned int index)
m_all_bboxes_dirty = true;
}
} else {
if (index >= (unsigned int) m_bboxes_dirty.size ()) {
m_bboxes_dirty.resize (index + 1, false);
}
if ((! m_all_bboxes_dirty && ! m_bboxes_dirty [index]) || m_busy) {
if ((! m_all_bboxes_dirty && (index >= (unsigned int) m_bboxes_dirty.size () || ! m_bboxes_dirty [index])) || m_busy) {
do_invalidate_bboxes (index); // must be called before the bboxes are invalidated (stopping of redraw thread requires this)
if (index >= (unsigned int) m_bboxes_dirty.size ()) {
m_bboxes_dirty.resize (index + 1, false);
}
m_bboxes_dirty [index] = true;
}
}

View File

@ -48,6 +48,21 @@ iterator_from_shape (const db::layer<Sh, db::unstable_layer_tag> &layer, const d
return layer.begin () + (shape.basic_ptr (typename Sh::tag ()) - &*layer.begin ());
}
template <class Sh>
inline bool
iterator_from_shape_is_valid (const db::layer<Sh, db::stable_layer_tag> &layer, const db::Shape &shape)
{
typename db::layer<Sh, db::stable_layer_tag>::iterator iter = shape.basic_iter (typename Sh::tag ());
return iter.vector () == layer.begin ().vector () && iter.is_valid ();
}
template <class Sh>
inline bool
iterator_from_shape_is_valid (const db::layer<Sh, db::unstable_layer_tag> &layer, const db::Shape &shape)
{
return layer.size () < (shape.basic_ptr (typename Sh::tag ()) - &*layer.begin ());
}
// -------------------------------------------------------------------------------
template <class Sh, class StableTag>
@ -260,10 +275,11 @@ Shapes::is_valid_shape_by_tag (Tag /*tag*/, const shape_type &shape) const
throw tl::Exception (tl::to_string (tr ("Function 'is_valid' is permitted only in editable mode")));
}
if (! shape.has_prop_id ()) {
return iterator_from_shape (get_layer<typename Tag::object_type, db::stable_layer_tag> (), shape).is_valid ();
typedef typename Tag::object_type s_type;
return iterator_from_shape_is_valid (get_layer<s_type, db::stable_layer_tag> (), shape);
} else {
typedef db::object_with_properties<typename Tag::object_type> swp_type;
return iterator_from_shape (get_layer<swp_type, db::stable_layer_tag> (), shape).is_valid ();
return iterator_from_shape_is_valid (get_layer<swp_type, db::stable_layer_tag> (), shape);
}
}

View File

@ -1594,6 +1594,14 @@ CODE
# @brief Specifies cell filters on the default source
# @synopsis select(args)
# See \Source#select for a description of that function.
# Using the global version does not create a new source, but
# modifies the default source.
#
# @code
# # Selects only B cell instances below the top cell
# select("-", "+B*")
# l1 = input(1, 0)
# @/code
def select(*args)
self._context("select") do

View File

@ -161,9 +161,11 @@ module DRC
# %DRC%
# @name select
# @brief Adds cell name expressions to the cell filters
# @synopsis source.select(filter1, filter2, ...)
# @synopsis new_source = source.select(filter1, filter2, ...)
# This method will construct a new source object with the given cell filters
# applied.
# applied. Note that there is a global version of "select" which does not
# create a new source, but acts on the default source.
#
# Cell filters will enable or disable cells plus their subtree.
# Cells can be switched on and off, which makes the hierarchy traversal
# stop or begin delivering shapes at the given cell. The arguments of
@ -184,8 +186,8 @@ module DRC
# code:
#
# @code
# layout_with_selection = source.select("-TOP", "+B")
# l1 = source.input(1, 0)
# source_with_selection = source.select("-TOP", "+B")
# l1 = source_with_selection.input(1, 0)
# ...
# @/code
#
@ -201,8 +203,8 @@ module DRC
# first "-*" selection, all cells including the children of "B" are disabled:
#
# @code
# layout_with_selection = source.select("-*", "+B")
# l1 = source.input(1, 0)
# source_with_selection = source.select("-*", "+B")
# l1 = source_with_selection.input(1, 0)
# ...
# @/code
#
@ -210,8 +212,8 @@ module DRC
# and will start with a disabled top cell regardless of its name:
#
# @code
# layout_with_selection = source.select("-", "+B")
# l1 = source.input(1, 0)
# source_with_selection = source.select("-", "+B")
# l1 = source_with_selection.input(1, 0)
# ...
# @/code

View File

@ -1028,13 +1028,16 @@ PartialService::PartialService (db::Manager *manager, lay::LayoutViewBase *view,
m_snap_to_objects (true),
m_top_level_sel (false),
m_hover (false),
m_hover_wait (false)
{
m_hover_wait (false),
dm_selection_to_view (this, &edt::PartialService::do_selection_to_view)
{
#if defined(HAVE_QT)
m_timer.setInterval (100 /*hover time*/);
m_timer.setSingleShot (true);
connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timeout ()));
#endif
mp_view->geom_changed_event.add (this, &edt::PartialService::selection_to_view);
}
PartialService::~PartialService ()
@ -2398,8 +2401,14 @@ PartialService::select (const db::DBox &box, SelectionMode mode)
return false;
}
void
void
PartialService::selection_to_view ()
{
dm_selection_to_view ();
}
void
PartialService::do_selection_to_view ()
{
// if dragging, establish the current displacement
db::DTrans move_trans;
@ -2424,6 +2433,17 @@ PartialService::selection_to_view ()
size_t n_marker = 0;
size_t n_inst_marker = 0;
// Reduce the selection to valid paths (issue-1145)
std::vector<partial_objects::iterator> invalid_objects;
for (partial_objects::iterator r = m_selection.begin (); r != m_selection.end (); ++r) {
if (! r->first.is_valid (view ())) {
invalid_objects.push_back (r);
}
}
for (auto i = invalid_objects.begin (); i != invalid_objects.end (); ++i) {
m_selection.erase (*i);
}
if (! m_selection.empty ()) {
// build the transformation variants cache

View File

@ -31,6 +31,7 @@
#include "layRubberBox.h"
#include "laySnap.h"
#include "tlAssert.h"
#include "tlDeferredExecution.h"
#include "edtUtils.h"
#include "edtConfig.h"
@ -339,11 +340,15 @@ private:
bool m_hover_wait;
db::DPoint m_hover_point;
// Deferred method to update the selection
tl::DeferredMethod<edt::PartialService> dm_selection_to_view;
void hover_reset ();
void clear_partial_transient_selection ();
bool partial_select (const db::DBox &box, lay::Editable::SelectionMode mode);
void selection_to_view ();
void do_selection_to_view ();
db::DPoint snap (const db::DPoint &p) const;
db::DVector snap (const db::DVector &p) const;

View File

@ -79,7 +79,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
m_seq (0),
dm_selection_to_view (this, &edt::Service::do_selection_to_view)
{
// .. nothing yet ..
mp_view->geom_changed_event.add (this, &edt::Service::selection_to_view);
}
Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
@ -99,7 +99,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
m_seq (0),
dm_selection_to_view (this, &edt::Service::do_selection_to_view)
{
// .. nothing yet ..
mp_view->geom_changed_event.add (this, &edt::Service::selection_to_view);
}
Service::~Service ()
@ -1511,6 +1511,19 @@ Service::do_selection_to_view ()
// build the transformation variants cache
TransformationVariants tv (view ());
// Reduce the selection to valid paths (issue-1145)
std::vector<std::set<lay::ObjectInstPath>::iterator> invalid_objects;
for (std::set<lay::ObjectInstPath>::iterator r = m_selection.begin (); r != m_selection.end (); ++r) {
if (! r->is_valid (view ())) {
invalid_objects.push_back (r);
}
}
for (auto i = invalid_objects.begin (); i != invalid_objects.end (); ++i) {
m_selection.erase (*i);
}
// Build markers
for (std::set<lay::ObjectInstPath>::iterator r = m_selection.begin (); r != m_selection.end (); ++r) {
const lay::CellView &cv = view ()->cellview (r->cv_index ());

View File

@ -167,7 +167,12 @@ gsi::Class<lay::ObjectInstPath> decl_ObjectInstPath ("lay", "ObjectInstPath",
"\n"
"This method has been introduced with version 0.24.\n"
) +
gsi::method ("cv_index", &lay::ObjectInstPath::cv_index,
gsi::method ("is_valid?", &lay::ObjectInstPath::is_valid, gsi::arg ("view"),
"@brief Gets a value indicating whether the instance path refers to a valid object in the context of the given view\n"
"\n"
"This predicate has been introduced in version 0.27.12.\n"
) +
gsi::method ("cv_index", &lay::ObjectInstPath::cv_index,
"@brief Gets the cellview index that describes which cell view the shape or instance is located in\n"
) +
gsi::method ("cv_index=", &lay::ObjectInstPath::set_cv_index, gsi::arg ("index"),

View File

@ -1597,6 +1597,14 @@ out = l1.drc(primary &amp; secondary(l2))
</ul>
<p>
See <a href="/about/drc_ref_source.xml#select">Source#select</a> for a description of that function.
Using the global version does not create a new source, but
modifies the default source.
</p><p>
<pre>
# Selects only B cell instances below the top cell
select("-", "+B*")
l1 = input(1, 0)
</pre>
</p>
<a name="sep"/><h2>"sep" - Synonym for "separation"</h2>
<keyword name="sep"/>

View File

@ -320,11 +320,13 @@ Use the global version of "polygons" without a source object to address the defa
<keyword name="select"/>
<p>Usage:</p>
<ul>
<li><tt>source.select(filter1, filter2, ...)</tt></li>
<li><tt>new_source = source.select(filter1, filter2, ...)</tt></li>
</ul>
<p>
This method will construct a new source object with the given cell filters
applied.
applied. Note that there is a global version of "select" which does not
create a new source, but acts on the default source.
</p><p>
Cell filters will enable or disable cells plus their subtree.
Cells can be switched on and off, which makes the hierarchy traversal
stop or begin delivering shapes at the given cell. The arguments of
@ -345,8 +347,8 @@ To disable the TOP cell but enabled a hypothetical cell B below the top cell, us
code:
</p><p>
<pre>
layout_with_selection = source.select("-TOP", "+B")
l1 = source.input(1, 0)
source_with_selection = source.select("-TOP", "+B")
l1 = source_with_selection.input(1, 0)
...
</pre>
</p><p>
@ -362,8 +364,8 @@ The following code will just select "B" without its children, because in the
first "-*" selection, all cells including the children of "B" are disabled:
</p><p>
<pre>
layout_with_selection = source.select("-*", "+B")
l1 = source.input(1, 0)
source_with_selection = source.select("-*", "+B")
l1 = source_with_selection.input(1, 0)
...
</pre>
</p><p>
@ -371,8 +373,8 @@ The short form "-" will disable the top cell. This code is identical to the firs
and will start with a disabled top cell regardless of its name:
</p><p>
<pre>
layout_with_selection = source.select("-", "+B")
l1 = source.input(1, 0)
source_with_selection = source.select("-", "+B")
l1 = source_with_selection.input(1, 0)
...
</pre>
</p>

View File

@ -26,6 +26,7 @@
#include "layObjectInstPath.h"
#include "layCellView.h"
#include "layLayoutViewBase.h"
#include "tlException.h"
namespace lay {
@ -39,6 +40,42 @@ ObjectInstPath::ObjectInstPath ()
// .. nothing yet ..
}
bool
ObjectInstPath::is_valid (lay::LayoutViewBase *view) const
{
const lay::CellView &cv = view->cellview (cv_index ());
if (! cv.is_valid ()) {
return false;
}
const db::Layout &ly = cv->layout ();
db::cell_index_type ci = topcell ();
if (! ly.is_valid_cell_index (ci)) {
return false;
}
for (auto p = begin (); p != end (); ++p) {
if (! ly.cell (ci).is_valid (p->inst_ptr)) {
return false;
}
ci = p->inst_ptr.cell_index ();
if (! ly.is_valid_cell_index (ci)) {
return false;
}
}
if (! is_cell_inst ()) {
if (! ly.is_valid_layer (layer ())) {
return false;
}
if (! ly.cell (ci).shapes (layer ()).is_valid (shape ())) {
return false;
}
}
return true;
}
db::cell_index_type
ObjectInstPath::cell_index_tot () const
{

View File

@ -37,7 +37,7 @@
namespace lay
{
class LayoutView;
class LayoutViewBase;
}
namespace lay {
@ -299,6 +299,15 @@ public:
m_seq = s;
}
/**
* @brief Gets a value indicating whether the object path is valid
*
* After the layout has been modified, this method is able to check
* whether the object path (including shape if applicable) still points
* to a valid object.
*/
bool is_valid (lay::LayoutViewBase *view) const;
private:
unsigned int m_cv_index;
db::cell_index_type m_topcell;

View File

@ -98,7 +98,7 @@ LayerSourceDialog::exec_dialog (std::string &s)
// NewLayoutPropertiesDialog implementation
NewLayoutPropertiesDialog::NewLayoutPropertiesDialog (QWidget *parent)
: QDialog (parent)
: QDialog (parent), m_default_dbu (0.0)
{
setObjectName (QString::fromUtf8 ("new_layout_properties_dialog"));
@ -117,14 +117,20 @@ NewLayoutPropertiesDialog::~NewLayoutPropertiesDialog ()
void
NewLayoutPropertiesDialog::tech_changed ()
{
double dbu = 0.001;
double dbu = 0.0;
int technology_index = mp_ui->tech_cbx->currentIndex ();
if (technology_index >= 0 && technology_index < (int) db::Technologies::instance ()->technologies ()) {
dbu = db::Technologies::instance ()->begin () [technology_index].dbu ();
}
m_default_dbu = dbu;
#if QT_VERSION >= 0x40700
mp_ui->dbu_le->setPlaceholderText (tl::to_qstring (tl::to_string (dbu)));
if (dbu > 1e-10) {
mp_ui->dbu_le->setPlaceholderText (tl::to_qstring (tl::to_string (dbu)));
} else {
mp_ui->dbu_le->setPlaceholderText (QString ());
}
#endif
}
@ -142,6 +148,8 @@ NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &ce
}
tech_changed ();
mp_ui->window_le->setText (tl::to_qstring (tl::to_string (size)));
if (dbu > 1e-10) {
mp_ui->dbu_le->setText (tl::to_qstring (tl::to_string (dbu)));
@ -174,7 +182,7 @@ NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &ce
if (! mp_ui->dbu_le->text ().isEmpty ()) {
tl::from_string_ext (tl::to_string (mp_ui->dbu_le->text ()), dbu);
} else {
dbu = 0.0;
dbu = m_default_dbu;
}
cell_name = tl::to_string (mp_ui->topcell_le->text ());

View File

@ -338,6 +338,7 @@ private:
virtual void accept ();
Ui::NewLayoutPropertiesDialog *mp_ui;
double m_default_dbu;
};
/**

View File

@ -390,10 +390,8 @@ BEGIN_PROTECTED
mp_private->view->manager ()->commit ();
insertItem (index, tl::to_qstring (lp.to_string ()));
setCurrentIndex (index);
mp_private->layers.push_back (std::make_pair (lp, int (l)));
// NOTE: add_new_layers has triggered update_layer_list which already added the new layer
set_current_layer (lp);
}

View File

@ -101,7 +101,7 @@ public:
* @brief The constructor
*/
OASISWriterOptions ()
: compression_level (2), write_cblocks (false), strict_mode (false), recompress (false), permissive (false), write_std_properties (1), subst_char ("*")
: compression_level (2), write_cblocks (true), strict_mode (true), recompress (false), permissive (false), write_std_properties (1), subst_char ("*")
{
// .. nothing yet ..
}

View File

@ -1176,6 +1176,11 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save
m_options = options.get_options<OASISWriterOptions> ();
mp_stream = &stream;
if (stream.is_compressing ()) {
std::string msg = tl::to_string (tr ("File compression is discouraged in OASIS, please use CBLOCK compression"));
tl::warn << msg;
}
double dbu = (options.dbu () == 0.0) ? layout.dbu () : options.dbu ();
m_sf = options.scale_factor () * (layout.dbu () / dbu);
if (fabs (m_sf - 1.0) < 1e-9) {

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>590</width>
<height>248</height>
<width>633</width>
<height>338</height>
</rect>
</property>
<property name="windowTitle">
@ -74,46 +74,35 @@
<property name="spacing">
<number>6</number>
</property>
<item row="4" column="2" colspan="3">
<widget class="QComboBox" name="std_prop_mode">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>No standard properties</string>
</property>
</item>
<item>
<property name="text">
<string>Global standard properties</string>
</property>
</item>
<item>
<property name="text">
<string>Global + per-cell bounding boxes</string>
</property>
</item>
</widget>
</item>
<item row="3" column="2" colspan="3">
<widget class="QCheckBox" name="strict_mode">
<item row="1" column="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Write strict-mode OASIS files</string>
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Strict mode</string>
</property>
</widget>
</item>
<item row="5" column="2" colspan="3">
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Standard properties</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Substitution character</string>
</property>
</widget>
</item>
<item row="8" column="2" colspan="3">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -169,17 +158,86 @@
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_9">
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Standard properties</string>
<string>0 (low)</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<item row="7" column="2" colspan="3">
<widget class="QComboBox" name="std_prop_mode">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>No standard properties</string>
</property>
</item>
<item>
<property name="text">
<string>Global standard properties</string>
</property>
</item>
<item>
<property name="text">
<string>Global + per-cell bounding boxes</string>
</property>
</item>
</widget>
</item>
<item row="5" column="2" colspan="3">
<widget class="QCheckBox" name="strict_mode">
<property name="text">
<string>Substitution character</string>
<string>Write strict-mode OASIS files</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="3">
<widget class="QCheckBox" name="write_cblocks">
<property name="text">
<string>Use CBLOCK compression for each cell (RFC1951)</string>
</property>
</widget>
</item>
<item row="9" column="2" colspan="3">
<widget class="QCheckBox" name="permissive">
<property name="text">
<string>Don't fail on paths with odd width and other odd shapes</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Compaction level
(repetition detection)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Permissive mode</string>
</property>
</widget>
</item>
@ -199,17 +257,54 @@
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="3" column="2" colspan="3">
<widget class="QFrame" name="cblock_warning_frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>0 (low)</string>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>File compression - i.e. &quot;.gz&quot; - is discouraged in OASIS, please consider using CBLOCK compression</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2" colspan="3">
@ -234,13 +329,6 @@
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
@ -248,30 +336,6 @@
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Compaction level
(repetition detection)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="3">
<widget class="QCheckBox" name="write_cblocks">
<property name="text">
<string>Use CBLOCK compression for each cell (RFC1951)</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
@ -289,17 +353,53 @@
</widget>
</item>
<item row="6" column="2" colspan="3">
<widget class="QCheckBox" name="permissive">
<property name="text">
<string>Don't fail on paths with odd width and other odd shapes</string>
<widget class="QFrame" name="strict_mode_warning_frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Permissive mode</string>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Strict mode is recommended as strict mode OASIS files can be read more efficiently by some readers</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
@ -329,6 +429,8 @@
<tabstop>strict_mode</tabstop>
<tabstop>subst_char</tabstop>
</tabstops>
<resources/>
<resources>
<include location="../../../../lay/lay/layResources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -24,9 +24,7 @@
#include "dbOASIS.h"
#include "dbOASISWriter.h"
#include "dbSaveLayoutOptions.h"
#include "layStream.h"
#include "ui_OASISWriterOptionPage.h"
#include "layOASISWriterPlugin.h"
#include <QFrame>
@ -36,25 +34,14 @@ namespace lay
// ---------------------------------------------------------------
// OASISWriterOptionPage definition and implementation
class OASISWriterOptionPage
: public StreamWriterOptionsPage
{
public:
OASISWriterOptionPage (QWidget *parent);
~OASISWriterOptionPage ();
void setup (const db::FormatSpecificWriterOptions *options, const db::Technology *tech);
void commit (db::FormatSpecificWriterOptions *options, const db::Technology *tech, bool gzip);
private:
Ui::OASISWriterOptionPage *mp_ui;
};
OASISWriterOptionPage::OASISWriterOptionPage (QWidget *parent)
: StreamWriterOptionsPage (parent)
{
mp_ui = new Ui::OASISWriterOptionPage ();
mp_ui->setupUi (this);
connect (mp_ui->write_cblocks, SIGNAL (clicked(bool)), this, SLOT (flags_changed()));
connect (mp_ui->strict_mode, SIGNAL (clicked(bool)), this, SLOT (flags_changed()));
}
OASISWriterOptionPage::~OASISWriterOptionPage ()
@ -69,13 +56,22 @@ OASISWriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const db
if (options) {
mp_ui->compression_slider->setValue (options->compression_level);
mp_ui->write_cblocks->setChecked (options->write_cblocks);
mp_ui->cblock_warning_frame->setEnabled (! options->write_cblocks);
mp_ui->strict_mode->setChecked (options->strict_mode);
mp_ui->strict_mode_warning_frame->setEnabled (! options->strict_mode);
mp_ui->std_prop_mode->setCurrentIndex (options->write_std_properties);
mp_ui->subst_char->setText (tl::to_qstring (options->subst_char));
mp_ui->permissive->setChecked (options->permissive);
}
}
void
OASISWriterOptionPage::flags_changed ()
{
mp_ui->cblock_warning_frame->setEnabled (! mp_ui->write_cblocks->isChecked ());
mp_ui->strict_mode_warning_frame->setEnabled (! mp_ui->strict_mode->isChecked ());
}
void
OASISWriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const db::Technology * /*tech*/, bool gzip)
{

View File

@ -24,10 +24,30 @@
#ifndef HDR_layOASISWriterPlugin_h
#define HDR_layOASISWriterPlugin_h
#include "layStream.h"
#include "ui_OASISWriterOptionPage.h"
namespace lay
{
// .. nothing yet (but needed for MOC) ..
class OASISWriterOptionPage
: public StreamWriterOptionsPage
{
Q_OBJECT
public:
OASISWriterOptionPage (QWidget *parent);
~OASISWriterOptionPage ();
void setup (const db::FormatSpecificWriterOptions *options, const db::Technology *tech);
void commit (db::FormatSpecificWriterOptions *options, const db::Technology *tech, bool gzip);
public slots:
void flags_changed ();
private:
Ui::OASISWriterOptionPage *mp_ui;
};
}

View File

@ -57,6 +57,10 @@ void run_test (tl::TestBase *_this, const char *file, bool scaling_test, int com
tl::OutputStream stream (tmp_file);
db::OASISWriter writer;
db::SaveLayoutOptions options;
db::OASISWriterOptions oasis_options;
oasis_options.write_cblocks = false;
oasis_options.strict_mode = false;
options.set_options (oasis_options);
writer.write (layout, stream, options);
}
@ -158,6 +162,7 @@ void run_test (tl::TestBase *_this, const char *file, bool scaling_test, int com
db::OASISWriter writer;
db::SaveLayoutOptions options;
db::OASISWriterOptions oasis_options;
oasis_options.write_cblocks = false;
oasis_options.strict_mode = false;
oasis_options.write_std_properties = 2;
options.set_options (oasis_options);
@ -557,6 +562,7 @@ TEST(100)
{
tl::OutputStream out (tmp_file);
db::SaveLayoutOptions options;
options.set_option_by_name ("oasis_strict_mode", false);
options.set_format ("OASIS");
db::Writer writer (options);
writer.write (g, out);
@ -1225,6 +1231,7 @@ TEST(115)
{
tl::OutputStream out (tmp_file);
db::SaveLayoutOptions options;
options.set_option_by_name ("oasis_strict_mode", false);
options.set_format ("OASIS");
db::Writer writer (options);
writer.write (g, out);
@ -1302,6 +1309,7 @@ TEST(116)
{
tl::OutputStream out (tmp_file);
db::SaveLayoutOptions write_options;
write_options.set_option_by_name ("oasis_strict_mode", false);
write_options.set_format ("OASIS");
db::Writer writer (write_options);
writer.write (g, out);
@ -1354,6 +1362,7 @@ TEST(116)
write_options.set_format ("OASIS");
db::OASISWriterOptions oas_write_options;
oas_write_options.write_std_properties = 0;
oas_write_options.strict_mode = false;
write_options.set_options (oas_write_options);
db::Writer writer (write_options);
writer.write (g, out);
@ -1403,6 +1412,7 @@ TEST(116)
write_options.set_format ("OASIS");
db::OASISWriterOptions oas_write_options;
oas_write_options.write_std_properties = 2;
oas_write_options.strict_mode = false;
write_options.set_options (oas_write_options);
db::Writer writer (write_options);
writer.write (g, out);
@ -1462,6 +1472,7 @@ TEST(116)
db::OASISWriterOptions oas_write_options;
oas_write_options.write_std_properties = 2;
oas_write_options.strict_mode = true;
oas_write_options.write_cblocks = false;
write_options.set_options (oas_write_options);
db::Writer writer (write_options);
writer.write (g, out);
@ -1522,6 +1533,7 @@ TEST(116)
tl::OutputStream out (tmp_file);
db::SaveLayoutOptions write_options;
write_options.set_format ("OASIS");
write_options.set_option_by_name ("oasis_strict_mode", false);
db::Writer writer (write_options);
writer.write (g, out);
}
@ -1572,6 +1584,7 @@ TEST(116)
db::SaveLayoutOptions write_options;
write_options.select_cell (c2.cell_index ());
write_options.set_format ("OASIS");
write_options.set_option_by_name ("oasis_strict_mode", false);
db::Writer writer (write_options);
writer.write (g, out);
}

View File

@ -726,6 +726,14 @@ public:
return false;
}
/**
* @brief Returns a value indicating whether that stream is compressing
*/
virtual bool is_compressing () const
{
return false;
}
/**
* @brief Rejects the output - for delegates supporting unrolling, this means the original file is restored
*/
@ -972,6 +980,11 @@ protected:
*/
virtual void seek_file (size_t /*s*/) { }
/**
* @brief Returns a value indicating whether this steam is compressing
*/
virtual bool is_compressing () const { return true; }
private:
// No copying
OutputZLibFile (const OutputZLibFile &);
@ -1244,6 +1257,14 @@ public:
}
}
/**
* @brief Returns a value indicating whether that stream is compressing
*/
bool is_compressing () const
{
return mp_delegate != 0 && mp_delegate->is_compressing ();
}
/**
* @brief Returns a value indicating whether that stream supports seek
*/

View File

@ -1122,7 +1122,11 @@ class DBLayoutTest(unittest.TestCase):
shape.set_property("42", "the answer")
ly.write(file_gds)
ly.write(file_oas)
opt = pya.SaveLayoutOptions()
opt.format = "OASIS"
opt.oasis_strict_mode = False
ly.write(file_oas, opt)
ly2 = pya.Layout()
ly2.read(file_gds)