1313#include < exception>
1414#include < iterator>
1515#include < mutex>
16+ #include < optional>
1617#include < set>
1718#include < string>
1819#include < utility>
1920#include < vector>
2021
2122#include " boost/geometry/geometry.hpp"
23+ #include " boost/geometry/index/parameters.hpp"
24+ #include " boost/geometry/index/predicates.hpp"
25+ #include " boost/geometry/index/rtree.hpp"
2226#include " gui/gui.h"
2327#include " layoutViewer.h"
2428#include " odb/db.h"
@@ -1265,7 +1269,7 @@ void RenderThread::drawChip(QPainter* painter,
12651269
12661270 utl::Timer inst_access_points;
12671271 if (viewer_->options_ ->areAccessPointsVisible ()) {
1268- drawAccessPoints (gui_painter, insts);
1272+ drawAccessPoints (gui_painter, block, bounds, insts);
12691273 }
12701274 debugPrint (logger_, GUI, " draw" , 1 , " access points {}" , inst_access_points);
12711275
@@ -1438,6 +1442,8 @@ void RenderThread::drawNetTracks(Painter& painter, odb::dbTechLayer* layer)
14381442}
14391443
14401444void RenderThread::drawAccessPoints (Painter& painter,
1445+ odb::dbBlock* block,
1446+ const odb::Rect& bounds,
14411447 const std::vector<odb::dbInst*>& insts)
14421448{
14431449 const int shape_limit = viewer_->shapeSizeLimit ();
@@ -1481,11 +1487,18 @@ void RenderThread::drawAccessPoints(Painter& painter,
14811487 }
14821488 }
14831489 }
1484- for (auto term : viewer_->getBlock ()->getBTerms ()) {
1485- if (restart_) {
1486- break ;
1487- }
1488- for (auto pin : term->getBPins ()) {
1490+
1491+ odb::dbTech* tech = block->getTech ();
1492+ for (odb::dbTechLayer* layer : tech->getLayers ()) {
1493+ for (const auto & [box, pin] : viewer_->search_ .searchBPins (block,
1494+ layer,
1495+ bounds.xMin (),
1496+ bounds.yMin (),
1497+ bounds.xMax (),
1498+ bounds.yMax ())) {
1499+ if (restart_) {
1500+ break ;
1501+ }
14891502 for (auto ap : pin->getAccessPoints ()) {
14901503 draw (ap, {});
14911504 }
@@ -1531,16 +1544,17 @@ void RenderThread::drawModuleView(QPainter* painter,
15311544
15321545void RenderThread::setupIOPins (odb::dbBlock* block, const odb::Rect& bounds)
15331546{
1534- pins_.clear ();
15351547 if (!viewer_->options_ ->areIOPinsVisible ()) {
1548+ pin_draw_names_ = false ;
15361549 return ;
15371550 }
15381551
15391552 const auto die_area = block->getDieArea ();
15401553 const auto die_width = die_area.dx ();
15411554 const auto die_height = die_area.dy ();
15421555
1543- if (viewer_->options_ ->areIOPinNamesVisible ()) {
1556+ pin_draw_names_ = viewer_->options_ ->areIOPinNamesVisible ();
1557+ if (pin_draw_names_) {
15441558 const double scale_factor
15451559 = 0.02 ; // 4 Percent of bounds is used to draw pin-markers
15461560 const int die_max_dim
@@ -1551,15 +1565,6 @@ void RenderThread::setupIOPins(odb::dbBlock* block, const odb::Rect& bounds)
15511565 pin_font_ = viewer_->options_ ->ioPinMarkersFont ();
15521566 const QFontMetrics font_metrics (pin_font_);
15531567
1554- QString largest_text;
1555- for (auto pin : block->getBTerms ()) {
1556- QString current_text = QString::fromStdString (pin->getName ());
1557- if (font_metrics.boundingRect (current_text).width ()
1558- > font_metrics.boundingRect (largest_text).width ()) {
1559- largest_text = std::move (current_text);
1560- }
1561- }
1562-
15631568 const int vertical_gap
15641569 = (viewer_->geometry ().height ()
15651570 - viewer_->getBounds ().dy () * viewer_->pixels_per_dbu_ )
@@ -1574,59 +1579,71 @@ void RenderThread::setupIOPins(odb::dbBlock* block, const odb::Rect& bounds)
15741579 - std::ceil (pin_max_size_) * viewer_->pixels_per_dbu_ ; // in pixels
15751580
15761581 int font_size = pin_font_.pointSize ();
1577- int largest_text_width = font_metrics.boundingRect (largest_text).width ();
15781582 const int drawing_font_size = 6 ; // in points
15791583
15801584 // when the size is minimum the text won't be drawn
15811585 const int minimum_font_size = drawing_font_size - 1 ;
15821586
1583- while (largest_text_width > available_space) {
1584- if (font_size == minimum_font_size) {
1587+ int largest_text_width = 0 ;
1588+ std::set<odb::dbBTerm*> checked;
1589+ odb::dbTech* tech = block->getTech ();
1590+ for (odb::dbTechLayer* layer : tech->getLayers ()) {
1591+ if (restart_) {
1592+ return ;
1593+ }
1594+ if (font_size <= minimum_font_size) {
15851595 break ;
15861596 }
1587- font_size -= 1 ;
1588- pin_font_.setPointSize (font_size);
1589- QFontMetrics current_font_metrics (pin_font_);
1590- largest_text_width
1591- = current_font_metrics.boundingRect (largest_text).width ();
1597+ for (const auto & [box, pin] :
1598+ viewer_->search_ .searchBPins (block,
1599+ layer,
1600+ bounds.xMin (),
1601+ bounds.yMin (),
1602+ bounds.xMax (),
1603+ bounds.yMax ())) {
1604+ if (restart_) {
1605+ return ;
1606+ }
1607+ odb::dbBTerm* bterm = pin->getBTerm ();
1608+ if (checked.find (bterm) != checked.end ()) {
1609+ continue ;
1610+ }
1611+ checked.insert (bterm);
1612+
1613+ QString current_text = QString::fromStdString (pin->getName ());
1614+ const int text_width = font_metrics.boundingRect (current_text).width ();
1615+ largest_text_width = std::max (text_width, largest_text_width);
1616+ while (largest_text_width > available_space) {
1617+ if (font_size <= minimum_font_size) {
1618+ break ;
1619+ }
1620+ font_size -= 1 ;
1621+ pin_font_.setPointSize (font_size);
1622+ QFontMetrics current_font_metrics (pin_font_);
1623+ largest_text_width
1624+ = current_font_metrics.boundingRect (current_text).width ();
1625+ }
1626+
1627+ if (font_size <= minimum_font_size) {
1628+ break ;
1629+ }
1630+ }
15921631 }
15931632
15941633 // draw names of pins when text height is at least 6 pts
15951634 pin_draw_names_ = font_size >= drawing_font_size;
15961635 } else {
15971636 pin_draw_names_ = false ;
15981637 }
1599-
1600- for (odb::dbBTerm* term : block->getBTerms ()) {
1601- if (restart_) {
1602- break ;
1603- }
1604- if (!viewer_->isNetVisible (term->getNet ())) {
1605- continue ;
1606- }
1607- for (odb::dbBPin* pin : term->getBPins ()) {
1608- odb::dbPlacementStatus status = pin->getPlacementStatus ();
1609- if (!status.isPlaced ()) {
1610- continue ;
1611- }
1612- for (odb::dbBox* box : pin->getBoxes ()) {
1613- if (!box) {
1614- continue ;
1615- }
1616-
1617- pins_[box->getTechLayer ()].emplace_back (term, box);
1618- }
1619- }
1620- }
16211638}
16221639
16231640void RenderThread::drawIOPins (Painter& painter,
16241641 odb::dbBlock* block,
16251642 const odb::Rect& bounds,
16261643 odb::dbTechLayer* layer)
16271644{
1628- const auto & pins = pins_[layer];
1629- if (pins. empty ()) {
1645+ if (!viewer_-> options_ -> areIOPinsVisible ()
1646+ || !viewer_-> options_ -> areIOPinNamesVisible ()) {
16301647 return ;
16311648 }
16321649
@@ -1659,10 +1676,11 @@ void RenderThread::drawIOPins(Painter& painter,
16591676
16601677 // RTree used to search for overlapping shapes and decide if rotation of
16611678 // text is needed.
1662- bgi::rtree<odb::Rect, bgi::quadratic<16 >> pin_text_spec_shapes;
1679+ using PinShapeTree = bgi::rtree<odb::Rect, bgi::quadratic<16 >>;
1680+ PinShapeTree pin_text_spec_shapes;
16631681 struct PinText
16641682 {
1665- odb::Rect rect;
1683+ std::optional< odb::Rect> rect;
16661684 bool can_rotate;
16671685 std::string text;
16681686 odb::Point pt;
@@ -1673,14 +1691,23 @@ void RenderThread::drawIOPins(Painter& painter,
16731691 painter.setPen (layer);
16741692 painter.setBrush (layer);
16751693
1676- for (const auto & [term, box] : pins) {
1694+ std::vector<odb::Rect> pin_text_spec_shape_rects;
1695+ for (const auto & [box, pin] : viewer_->search_ .searchBPins (block,
1696+ layer,
1697+ bounds.xMin (),
1698+ bounds.yMin (),
1699+ bounds.xMax (),
1700+ bounds.yMax ())) {
16771701 if (restart_) {
16781702 break ;
16791703 }
1680- const auto pin_dir = term->getIoType ();
16811704
1682- Point pin_center ((box->xMin () + box->xMax ()) / 2 ,
1683- (box->yMin () + box->yMax ()) / 2 );
1705+ odb::dbBTerm* term = pin->getBTerm ();
1706+ if (!viewer_->options_ ->isNetVisible (term->getNet ())) {
1707+ continue ;
1708+ }
1709+
1710+ const Point pin_center = box->getBox ().center ();
16841711
16851712 auto dist_to_left = std::abs (box->xMin () - die_area.xMin ());
16861713 auto dist_to_right = std::abs (box->xMax () - die_area.xMax ());
@@ -1716,6 +1743,7 @@ void RenderThread::drawIOPins(Painter& painter,
17161743
17171744 // select marker
17181745 const std::vector<Point>* template_points = &bi_marker;
1746+ const auto pin_dir = term->getIoType ();
17191747 if (pin_dir == odb::dbIoType::INPUT) {
17201748 template_points = &in_marker;
17211749 } else if (pin_dir == odb::dbIoType::OUTPUT) {
@@ -1724,6 +1752,7 @@ void RenderThread::drawIOPins(Painter& painter,
17241752
17251753 // make new marker based on pin location
17261754 std::vector<Point> marker;
1755+ marker.reserve (template_points->size ());
17271756 for (const auto & pt : *template_points) {
17281757 Point new_pt = pt;
17291758 xfm.apply (new_pt);
@@ -1766,13 +1795,15 @@ void RenderThread::drawIOPins(Painter& painter,
17661795 pin_specs.text );
17671796 text_rect.bloat (text_margin, text_rect);
17681797 pin_specs.rect = text_rect;
1769- pin_text_spec_shapes.insert (pin_specs.rect );
1770- } else {
1771- pin_specs.rect = odb::Rect ();
1798+ pin_text_spec_shape_rects.push_back (text_rect);
17721799 }
17731800 pin_text_spec.push_back (std::move (pin_specs));
17741801 }
17751802 }
1803+ if (!pin_text_spec_shape_rects.empty ()) {
1804+ pin_text_spec_shapes = PinShapeTree (pin_text_spec_shape_rects.begin (),
1805+ pin_text_spec_shape_rects.end ());
1806+ }
17761807
17771808 painter.setPen (layer);
17781809 auto color = painter.getPenColor ();
@@ -1787,10 +1818,10 @@ void RenderThread::drawIOPins(Painter& painter,
17871818
17881819 bool do_rotate = false ;
17891820 auto anchor = pin.anchor ;
1790- if (pin.can_rotate ) {
1791- if (pin_text_spec_shapes.qbegin (bgi::intersects (pin.rect )
1821+ if (pin.can_rotate && pin. rect ) {
1822+ if (pin_text_spec_shapes.qbegin (bgi::intersects (* pin.rect )
17921823 && bgi::satisfies ([&](const auto & other) {
1793- return !bg::equals (other, pin.rect );
1824+ return !bg::equals (other, * pin.rect );
17941825 }))
17951826 != pin_text_spec_shapes.qend ()) {
17961827 // adjust anchor
0 commit comments