From 62b59fe71c34c2f562ab24270724b12579f05d75 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 20 Sep 2017 22:52:52 +0200 Subject: [PATCH] Reworked the XOR progress UI for better performance. --- src/ext/ext/extXORProgress.cc | 121 +++++++++++++++++++++++--------- src/ext/ext/extXORProgress.h | 6 +- src/ext/ext/extXORToolDialog.cc | 33 +++++---- 3 files changed, 108 insertions(+), 52 deletions(-) diff --git a/src/ext/ext/extXORProgress.cc b/src/ext/ext/extXORProgress.cc index 06fb93dc1..4b327850b 100644 --- a/src/ext/ext/extXORProgress.cc +++ b/src/ext/ext/extXORProgress.cc @@ -32,6 +32,46 @@ namespace ext { +static inline void merge (size_t &a, size_t b) +{ + if (a == missing_in_a || a == missing_in_a) { + // leave a + } else if (b == missing_in_a || b == missing_in_a) { + a = b; + } else { + a += b; + } +} + +static void merge (std::vector > &a, const std::vector > &b) +{ + if (a.size () < b.size ()) { + a.resize (b.size (), std::vector ()); + } + + std::vector >::iterator ia = a.begin (); + for (std::vector >::const_iterator ib = b.begin (); ib != b.end (); ++ib, ++ia) { + if (ia->size () < ib->size ()) { + ia->resize (ib->size (), 0); + } + std::vector::iterator ja = ia->begin (); + for (std::vector::const_iterator jb = ib->begin (); jb != ib->end (); ++jb, ++ja) { + merge (*ja, *jb); + } + } +} + +static size_t sum (const std::vector > &b) +{ + size_t n = 0; + for (std::vector >::const_iterator i = b.begin (); i != b.end (); ++i) { + for (std::vector::const_iterator j = i->begin (); j != i->end (); ++j) { + n += *j; + } + } + return n; +} + // -------------------------------------------------------------------------------------------------- // The progress widget class @@ -78,7 +118,7 @@ public: return QSize (int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width, (m_line_height + m_spacing) * m_max_lines + m_font_height * 2 + m_spacing); } - void set_results (double dbu, int nx, int ny, const std::map, std::map, size_t> > &results, const std::map &count_per_layer, const std::vector &tolerances) + void set_results (double dbu, int nx, int ny, const std::map, std::vector > > &results, const std::map &count_per_layer, const std::vector &tolerances) { m_labels.clear (); m_layer_labels.clear (); @@ -135,45 +175,51 @@ public: size_t tot_count = 0; - for (std::map, std::map, size_t> >::const_iterator r = results.begin (); r != results.end (); ++r) { + std::map, std::vector > >::const_iterator rm = results.find (std::make_pair (c->first, *t)); + if (rm != results.end ()) { - const std::map, size_t> &rm = r->second; + const std::vector > &counts = rm->second; + tot_count = sum (counts); - std::map, size_t>::const_iterator rl = rm.find (std::make_pair (c->first, *t)); - if (rl != rm.end ()) { + int ix = 0; + for (std::vector >::const_iterator c = counts.begin (); c != counts.end (); ++c, ++ix) { - tot_count += rl->second; + int iy = 0; + for (std::vector::const_iterator cc = c->begin (); cc != c->end (); ++cc, ++iy) { - QImage *img = 0; - if (rl->second == 0) { - img = &m_green_images.back ().back (); - } else if (rl->second == missing_in_a) { - m_blue_images.back ().back ().fill (Qt::white); - } else if (rl->second == missing_in_b) { - m_yellow_images.back ().back ().fill (Qt::white); - } else { - img = &m_red_images.back ().back (); - } - - if (img) { - if (nx == 0 || ny == 0) { - img->fill (Qt::white); + QImage *img = 0; + if (*cc == 0) { + img = &m_green_images.back ().back (); + } else if (*cc == missing_in_a) { + m_blue_images.back ().back ().fill (Qt::white); + } else if (*cc == missing_in_b) { + m_yellow_images.back ().back ().fill (Qt::white); } else { + img = &m_red_images.back ().back (); + } - int ix = r->first.first; - int iy = r->first.second; + if (img) { - int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny; - int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny; - int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx; - int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx; + if (nx == 0 || ny == 0) { + + img->fill (Qt::white); + + } else { + + int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny; + int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny; + int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx; + int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx; + + // "draw" the field + for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) { + *((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1)); + } - // "draw" the field - for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) { - *((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1)); } } + } } @@ -333,17 +379,26 @@ void XORProgress::render_progress (QWidget *widget) const } } -void XORProgress::set_results (double dbu, int nx, int ny, const std::map, std::map, size_t> > &results, const std::map &count_per_layer, const std::vector &tol) +void XORProgress::configure (double dbu, int nx, int ny, const std::vector &tol) { - if (m_count_per_layer != count_per_layer) { + if (m_tolerances != tol || fabs (m_dbu - dbu) > 1e-6 || m_nx != nx || m_ny != ny) { m_dbu = dbu; m_nx = nx; m_ny = ny; - m_results = results; m_tolerances = tol; - m_count_per_layer = count_per_layer; m_needs_update = true; } } +void XORProgress::merge_results (std::map, std::vector > > &results) +{ + for (std::map, std::vector > >::const_iterator r = results.begin (); r != results.end (); ++r) { + m_needs_update = true; + merge (m_results [r->first], r->second); + merge (m_count_per_layer [r->first.first], sum (r->second)); + } + + results.clear (); +} + } diff --git a/src/ext/ext/extXORProgress.h b/src/ext/ext/extXORProgress.h index 3b4abbe1c..d414271c1 100644 --- a/src/ext/ext/extXORProgress.h +++ b/src/ext/ext/extXORProgress.h @@ -54,10 +54,12 @@ public: virtual QWidget *progress_widget () const; virtual void render_progress (QWidget *widget) const; - void set_results (double dbu, int nx, int ny, const std::map, std::map, size_t> > &results, const std::map &count_per_layer, const std::vector &tol); + + void configure (double dbu, int nx, int ny, const std::vector &tol); + void merge_results (std::map, std::vector > > &results); private: - std::map, std::map, size_t> > m_results; + std::map, std::vector > > m_results; std::map m_count_per_layer; std::vector m_tolerances; bool m_needs_update; diff --git a/src/ext/ext/extXORToolDialog.cc b/src/ext/ext/extXORToolDialog.cc index 6d678cd2d..9d561b857 100644 --- a/src/ext/ext/extXORToolDialog.cc +++ b/src/ext/ext/extXORToolDialog.cc @@ -390,10 +390,8 @@ public: m_rdb (rdb), m_rdb_cell (rdb_cell), m_progress (0), - m_update_results (false), m_nx (0), m_ny (0) { - // .. nothing yet .. } output_mode_t output_mode () const @@ -457,16 +455,21 @@ public: void add_results (const db::LayerProperties &lp, db::Coord tol, size_t n, size_t ix, size_t iy) { QMutexLocker locker (&m_mutex); - if (n == missing_in_a || n == missing_in_b) { - m_results [std::make_pair (ix, iy)][std::make_pair (lp, tol)] = n; - m_count_per_layer [lp] = n; - } else { - // NOTE: we will not get a "normal" n after missing_in_a or missing_in_b - m_results [std::make_pair (ix, iy)][std::make_pair (lp, tol)] += n; - m_count_per_layer [lp] += n; + + std::vector > &cc = m_results [std::make_pair (lp, tol)]; + if (cc.size () <= ix) { + cc.resize (ix + 1, std::vector ()); + } + if (cc [ix].size () <= iy) { + cc [ix].resize (iy + 1, 0); } - m_update_results = true; + if (n == missing_in_a || n == missing_in_b) { + cc[ix][iy] = n; + } else { + // NOTE: we will not get a "normal" n after missing_in_a or missing_in_b + cc[ix][iy] += n; + } } void update_progress (XORProgress &progress) @@ -475,10 +478,8 @@ public: { QMutexLocker locker (&m_mutex); p = m_progress; - if (m_update_results) { - progress.set_results (m_dbu, m_nx, m_ny, m_results, m_count_per_layer, m_tolerances); - m_update_results = false; - } + progress.configure (m_dbu, m_nx, m_ny, m_tolerances); + progress.merge_results (m_results); } progress.set (p, true /*force yield*/); @@ -550,10 +551,8 @@ private: unsigned int m_progress; QMutex m_mutex; std::string m_result_string; - bool m_update_results; size_t m_nx, m_ny; - std::map, std::map, size_t> > m_results; - std::map m_count_per_layer; + std::map, std::vector > > m_results; }; class XORTask