Bugfix, text reference made the program assert

This commit is contained in:
Matthias Koefferlein 2023-05-11 18:57:24 +02:00
parent c45d1d70d4
commit 1422dfb93d
7 changed files with 112 additions and 43 deletions

View File

@ -177,12 +177,15 @@ hershey_text_box (const std::string &s, unsigned int f)
} }
hl += h; hl += h;
return db::DBox (0, 0, wl, hl); return db::DBox (0, fp->ymin, wl, hl);
} }
void void
hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halign, VAlign valign, std::vector<db::DPoint> &linestarts) hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halign, VAlign valign, std::vector<db::DPoint> &linestarts, double &left, double &bottom)
{ {
left = 0.0;
bottom = 0.0;
HersheyFont *fp = fonts [f]; HersheyFont *fp = fonts [f];
int hl = 0; int hl = 0;
@ -234,6 +237,13 @@ hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halig
p += db::DVector (0, l->y ()); p += db::DVector (0, l->y ());
} }
*l = p; *l = p;
if (l == linestarts.begin ()) {
left = l->x ();
bottom = l->y ();
} else {
left = std::min (left, l->x ());
bottom = std::min (bottom, l->y ());
}
} }
} }

View File

@ -38,7 +38,7 @@ struct HersheyFont;
DB_PUBLIC int hershey_font_width (unsigned int f); DB_PUBLIC int hershey_font_width (unsigned int f);
DB_PUBLIC int hershey_font_height (unsigned int f); DB_PUBLIC int hershey_font_height (unsigned int f);
DB_PUBLIC db::DBox hershey_text_box (const std::string &s, unsigned int f); DB_PUBLIC db::DBox hershey_text_box (const std::string &s, unsigned int f);
DB_PUBLIC void hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halign, VAlign valign, std::vector<db::DPoint> &linestarts); DB_PUBLIC void hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halign, VAlign valign, std::vector<db::DPoint> &linestarts, double &left, double &bottom);
DB_PUBLIC std::vector<std::string> hershey_font_names (); DB_PUBLIC std::vector<std::string> hershey_font_names ();
DB_PUBLIC size_t hershey_count_edges (const std::string &s, unsigned int f); DB_PUBLIC size_t hershey_count_edges (const std::string &s, unsigned int f);
@ -137,7 +137,8 @@ struct DB_PUBLIC_TEMPLATE hershey
hershey () hershey ()
: m_string (), : m_string (),
m_font (DefaultFont), m_font (DefaultFont),
m_scale (1.0) m_scale (1.0),
m_left (0.0), m_bottom (0.0)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -150,7 +151,8 @@ struct DB_PUBLIC_TEMPLATE hershey
hershey (const std::string &s, Font f) hershey (const std::string &s, Font f)
: m_string (s), : m_string (s),
m_font (f), m_font (f),
m_scale (1.0) m_scale (1.0),
m_left (0.0), m_bottom (0.0)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -181,9 +183,7 @@ struct DB_PUBLIC_TEMPLATE hershey
db::DBox bbox () const db::DBox bbox () const
{ {
db::DBox b = hershey_text_box (m_string, m_font); db::DBox b = hershey_text_box (m_string, m_font);
if (! m_linestarts.empty ()) { b.move (db::DVector (m_left, m_bottom));
b.move (m_linestarts.back () - db::DPoint ());
}
return b * m_scale; return b * m_scale;
} }
@ -220,7 +220,7 @@ struct DB_PUBLIC_TEMPLATE hershey
db::DPoint p1 (b.p1 ().x () / m_scale, b.p1 ().y () / m_scale); db::DPoint p1 (b.p1 ().x () / m_scale, b.p1 ().y () / m_scale);
db::DPoint p2 (b.p2 ().x () / m_scale, b.p2 ().y () / m_scale); db::DPoint p2 (b.p2 ().x () / m_scale, b.p2 ().y () / m_scale);
hershey_justify (m_string, m_font, db::DBox (p1, p2), halign, valign, m_linestarts); hershey_justify (m_string, m_font, db::DBox (p1, p2), halign, valign, m_linestarts, m_left, m_bottom);
} else { } else {
@ -245,7 +245,7 @@ struct DB_PUBLIC_TEMPLATE hershey
if (m_scale > 1e-6) { if (m_scale > 1e-6) {
db::DPoint p1 (b.p1 ().x () / m_scale, b.p1 ().y () / m_scale); db::DPoint p1 (b.p1 ().x () / m_scale, b.p1 ().y () / m_scale);
db::DPoint p2 (b.p2 ().x () / m_scale, b.p2 ().y () / m_scale); db::DPoint p2 (b.p2 ().x () / m_scale, b.p2 ().y () / m_scale);
hershey_justify (m_string, m_font, db::DBox (p1, p2), halign, valign, m_linestarts); hershey_justify (m_string, m_font, db::DBox (p1, p2), halign, valign, m_linestarts, m_left, m_bottom);
} }
} }
@ -294,6 +294,7 @@ private:
Font m_font; Font m_font;
double m_scale; double m_scale;
std::vector <db::DPoint> m_linestarts; std::vector <db::DPoint> m_linestarts;
double m_left, m_bottom;
}; };
/** /**

View File

@ -856,7 +856,9 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
if (text_info ()) { if (text_info ()) {
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t; db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
db::Box tb = t_dbu.inverted () * text_info ()->bbox (t_dbu * shape->text (), vp); db::Text text;
shape->text (text);
db::Box tb = t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp);
if (tb.inside (hit_box)) { if (tb.inside (hit_box)) {
edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0)); edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
} }
@ -1000,7 +1002,9 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
if (text_info ()) { if (text_info ()) {
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t; db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
db::Box tb (t_dbu.inverted () * text_info ()->bbox (t_dbu * shape->text (), vp)); db::Text text;
shape->text (text);
db::Box tb (t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp));
if (tb.contains (hit_box.center ())) { if (tb.contains (hit_box.center ())) {
d = tp.distance (hit_box.center ()); d = tp.distance (hit_box.center ());
edge_sel.clear (); edge_sel.clear ();

View File

@ -384,13 +384,6 @@ ShapeFinder::find_internal (lay::LayoutViewBase *view, unsigned int cv_index, co
m_topcell = cv.cell_index (); m_topcell = cv.cell_index ();
db::DBox scan_region_mu = region_mu;
if (mp_text_info) {
// for catching all labels we search the whole view area
// @@@ multiple passes - with and without texts (with texts with big area)
scan_region_mu = view->viewport ().box ();
}
mp_prop_sel = prop_sel; mp_prop_sel = prop_sel;
m_inv_prop_sel = inv_prop_sel; m_inv_prop_sel = inv_prop_sel;
@ -405,13 +398,34 @@ ShapeFinder::find_internal (lay::LayoutViewBase *view, unsigned int cv_index, co
max_level = hier_sel.to_level (ctx_path_length, max_level); max_level = hier_sel.to_level (ctx_path_length, max_level);
} }
// actually find auto flags_saved = m_flags;
try { try {
start (view, m_cv_index, trans_mu, region_mu, scan_region_mu, min_level, max_level, layers);
if ((m_flags & db::ShapeIterator::Texts) != 0 && mp_text_info) {
m_flags = db::ShapeIterator::Texts;
// for catching all labels we search the whole view area
db::DBox scan_region_mu = view->viewport ().box ();
start (view, m_cv_index, trans_mu, region_mu, scan_region_mu, min_level, max_level, layers);
m_flags = db::ShapeIterator::flags_type (flags_saved - db::ShapeIterator::Texts);
}
// another pass with tight search box and without texts
start (view, m_cv_index, trans_mu, region_mu, region_mu, min_level, max_level, layers);
} catch (StopException) { } catch (StopException) {
// .. // ...
} catch (...) {
m_flags = flags_saved;
throw;
} }
m_flags = flags_saved;
// return true if anything was found // return true if anything was found
return ! m_founds.empty (); return ! m_founds.empty ();
} }
@ -471,7 +485,9 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db:
db::Box bbox; db::Box bbox;
if (text_info () && shape->is_text ()) { if (text_info () && shape->is_text ()) {
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t; db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
bbox = t_dbu.inverted () * text_info ()->bbox (t_dbu * shape->text (), vp); db::Text text;
shape->text (text);
bbox = t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp);
} else { } else {
bbox = shape->bbox (); bbox = shape->bbox ();
} }
@ -565,7 +581,9 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db:
db::Box box = shape->bbox (); db::Box box = shape->bbox ();
if (text_info () && shape->is_text ()) { if (text_info () && shape->is_text ()) {
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t; db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
box = t_dbu.inverted () * text_info ()->bbox (t_dbu * shape->text (), vp); db::Text text;
shape->text (text);
box = t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp);
} }
// point-like boxes are handles which attract the finder // point-like boxes are handles which attract the finder

View File

@ -36,6 +36,13 @@
namespace lay namespace lay
{ {
static db::DVector text_box_enlargement (const db::DCplxTrans &vp_trans)
{
// 4.0 is the text box border in pixels
double b = 4.0 / vp_trans.mag ();
return db::DVector (b, b);
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void render_cell_inst (const db::Layout &layout, const db::CellInstArray &inst, const db::CplxTrans &trans, lay::Renderer &r, void render_cell_inst (const db::Layout &layout, const db::CellInstArray &inst, const db::CplxTrans &trans, lay::Renderer &r,
@ -630,7 +637,9 @@ ShapeMarker::render (const Viewport &vp, ViewObjectCanvas &canvas)
// draw a frame around the text // draw a frame around the text
lay::TextInfo ti (view ()); lay::TextInfo ti (view ());
db::DCplxTrans vp_trans = vp.trans () * *tr; db::DCplxTrans vp_trans = vp.trans () * *tr;
db::DBox box = ti.bbox (trans () * m_shape.text (), vp_trans).enlarged (db::DVector (2.0 / vp_trans.mag (), 2.0 / vp_trans.mag ())); db::Text t;
m_shape.text (t);
db::DBox box = ti.bbox (trans () * t, vp_trans).enlarged (text_box_enlargement (vp_trans));
r.draw (box, vp_trans, 0, text, 0, 0); r.draw (box, vp_trans, 0, text, 0, 0);
} }
r.draw (m_shape, t, fill, contour, vertex, text); r.draw (m_shape, t, fill, contour, vertex, text);
@ -641,7 +650,9 @@ ShapeMarker::render (const Viewport &vp, ViewObjectCanvas &canvas)
if (m_shape.is_text () && text) { if (m_shape.is_text () && text) {
// draw a frame around the text // draw a frame around the text
lay::TextInfo ti (view ()); lay::TextInfo ti (view ());
db::DBox box = ti.bbox (trans () * m_shape.text (), vp.trans ()).enlarged (db::DVector (2.0 / vp.trans ().mag (), 2.0 / vp.trans ().mag ())); db::Text t;
m_shape.text (t);
db::DBox box = ti.bbox (trans () * t, vp.trans ()).enlarged (text_box_enlargement (vp.trans ()));
r.draw (box, vp.trans (), 0, text, 0, 0); r.draw (box, vp.trans (), 0, text, 0, 0);
} }
r.draw (m_shape, t, fill, contour, vertex, text); r.draw (m_shape, t, fill, contour, vertex, text);
@ -1101,8 +1112,9 @@ Marker::draw (lay::Renderer &r, const db::CplxTrans &t, lay::CanvasPlane *fill,
if (view () && text) { if (view () && text) {
// draw a frame around the text // draw a frame around the text
lay::TextInfo ti (view ()); lay::TextInfo ti (view ());
db::DBox box = ti.bbox (*m_object.dtext, db::DCplxTrans (t)).enlarged (db::DVector (2.0 / t.mag (), 2.0 / t.mag ())); db::DCplxTrans dt (t);
r.draw (box, db::DCplxTrans (t), 0, text, 0, 0); db::DBox box = ti.bbox (*m_object.dtext, dt).enlarged (text_box_enlargement (dt));
r.draw (box, dt, 0, text, 0, 0);
} }
r.draw (*m_object.dtext, db::DCplxTrans (t), fill, contour, vertex, text); r.draw (*m_object.dtext, db::DCplxTrans (t), fill, contour, vertex, text);
} else if (m_type == Edge) { } else if (m_type == Edge) {
@ -1303,7 +1315,7 @@ DMarker::render (const Viewport &vp, ViewObjectCanvas &canvas)
if (view () && text) { if (view () && text) {
// draw a frame around the text // draw a frame around the text
lay::TextInfo ti (view ()); lay::TextInfo ti (view ());
db::DBox box = ti.bbox (*m_object.text, t).enlarged (db::DVector (2.0 / t.mag (), 2.0 / t.mag ())); db::DBox box = ti.bbox (*m_object.text, t).enlarged (text_box_enlargement (t));
r.draw (box, t, 0, text, 0, 0); r.draw (box, t, 0, text, 0, 0);
} }
r.draw (*m_object.text, t, fill, contour, vertex, text); r.draw (*m_object.text, t, fill, contour, vertex, text);

View File

@ -53,14 +53,14 @@ TextInfo::bbox (const db::DText &text, const db::DCplxTrans &vp_trans) const
// offset in pixels (space between origin and text) // offset in pixels (space between origin and text)
const double offset = 2.0; const double offset = 2.0;
db::DFTrans fp (db::DFTrans::r0); db::DTrans tt = text.trans ();
db::DCoord h; db::DCoord h;
db::Font font = text.font () == db::NoFont ? m_default_font : text.font (); db::Font font = text.font () == db::NoFont ? m_default_font : text.font ();
if (m_apply_text_trans && font != db::NoFont && font != db::DefaultFont) { if (m_apply_text_trans && font != db::NoFont && font != db::DefaultFont) {
fp = db::DFTrans (vp_trans.fp_trans () * text.trans ().fp_trans ());
h = vp_trans.ctrans (text.size () > 0 ? text.size () : m_default_text_size); h = vp_trans.ctrans (text.size () > 0 ? text.size () : m_default_text_size);
} else { } else {
tt = db::DTrans (tt.disp ());
h = vp_trans.ctrans (m_default_text_size); h = vp_trans.ctrans (m_default_text_size);
} }
@ -83,9 +83,9 @@ TextInfo::bbox (const db::DText &text, const db::DCplxTrans &vp_trans) const
db::DVector tp1 (fx * offset, fy * offset + (fy - 1) * 0.5 * h); db::DVector tp1 (fx * offset, fy * offset + (fy - 1) * 0.5 * h);
db::DVector tp2 (fx * offset, fy * offset + (fy + 1) * 0.5 * h); db::DVector tp2 (fx * offset, fy * offset + (fy + 1) * 0.5 * h);
db::DPoint dp = vp_trans * (db::DPoint () + text.trans ().disp ()); db::DPoint dp = vp_trans * db::DPoint ();
db::DBox b (dp + fp (tp1), dp + fp (tp2)); db::DBox b (dp + tp1, dp + tp2);
if (font == db::DefaultFont) { if (font == db::DefaultFont) {
@ -154,13 +154,13 @@ TextInfo::bbox (const db::DText &text, const db::DCplxTrans &vp_trans) const
} }
return db::DBox (xleft, ybottom, xright, ytop).transformed (vp_trans.inverted ()); return db::DBox (xleft, ybottom, xright, ytop).transformed (vp_trans.inverted ()).transformed (tt);
} else { } else {
db::DHershey ht (text.string (), font); db::DHershey ht (text.string (), font);
ht.justify (b.transformed (vp_trans.inverted ()), halign, valign); ht.justify (b.transformed (vp_trans.inverted ()), halign, valign);
return ht.bbox (); return ht.bbox ().transformed (tt);
} }
} }

View File

@ -44,46 +44,70 @@ TEST(1)
db::DText text3; db::DText text3;
// Default font
lay::TextInfo ti (&lv); lay::TextInfo ti (&lv);
EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,22;36,37)"); EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,22;36,37)");
EXPECT_EQ (ti.bbox (text, db::DCplxTrans (2.0)).to_string (), "(11,21;23,28.5)"); EXPECT_EQ (ti.bbox (text, db::DCplxTrans (2.0)).to_string (), "(11,21;23,28.5)");
EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,22;60,52)"); EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,22;60,52)");
// valign
text3 = text2; text3 = text2;
text3.valign (db::VAlignCenter); text3.valign (db::VAlignCenter);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,5;60,35)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,5;60,35)");
text3.valign (db::VAlignTop); text3.valign (db::VAlignTop);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-12;60,18)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-12;60,18)");
// halign
text3 = text2; text3 = text2;
text3.halign (db::HAlignCenter); text3.halign (db::HAlignCenter);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-14,22;34,52)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-14,22;34,52)");
text3.halign (db::HAlignRight); text3.halign (db::HAlignRight);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-40,22;8,52)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-40,22;8,52)");
// Herschey font
lv.text_font (db::Font::StickFont); lv.text_font (db::Font::StickFont);
ti = lay::TextInfo (&lv); ti = lay::TextInfo (&lv);
EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,22;72,47)"); EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,15;72,47)");
EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,22;134,83)"); EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,15;134,83)");
// valign
text3 = text2; text3 = text2;
text3.valign (db::VAlignCenter); text3.valign (db::VAlignCenter);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-10.5;134,50.5)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-17.5;134,50.5)");
text3.valign (db::VAlignTop); text3.valign (db::VAlignTop);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-43;134,18)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,-50;134,18)");
// halign
text3 = text2; text3 = text2;
text3.halign (db::HAlignCenter); text3.halign (db::HAlignCenter);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-51,22;71,83)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-51,15;71,83)");
text3.halign (db::HAlignRight); text3.halign (db::HAlignRight);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-114,22;8,83)"); EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-114,15;8,83)");
// smaller size as default
lv.default_text_size (4.2); lv.default_text_size (4.2);
ti = lay::TextInfo (&lv); ti = lay::TextInfo (&lv);
EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,22;24,27)"); EXPECT_EQ (ti.bbox (text, db::DCplxTrans ()).to_string (), "(12,20.6;24,27)");
EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,22;36.4,34.2)"); EXPECT_EQ (ti.bbox (text2, db::DCplxTrans ()).to_string (), "(12,20.6;36.4,34.2)");
// text with explicit size
text3 = text2;
text3.size (21);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,15;134,83)");
// text with rotation
text3.trans (db::DTrans (1, db::DVector (10.0, 20.0)));
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(-53,22;15,144)");
// text with rotation and default font (-> rotation ignored)
text3.font (db::Font::DefaultFont);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,22;60,52)");
text3.font (db::Font::StickFont);
// apply_text_trans = false
lv.apply_text_trans (false);
ti = lay::TextInfo (&lv);
EXPECT_EQ (ti.bbox (text3, db::DCplxTrans ()).to_string (), "(12,20.6;36.4,34.2)");
} }