/* KLayout Layout Viewer Copyright (C) 2006-2017 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 "dbLayout.h" #include "dbRecursiveShapeIterator.h" #include "dbBoxConvert.h" #include "layMarker.h" #include "laySnap.h" #include "layCanvasPlane.h" #include "layViewOp.h" #include "layRenderer.h" #include "layLayoutView.h" #include "tlAssert.h" namespace lay { // ------------------------------------------------------------------------ void render_cell_inst (const db::Layout &layout, const db::CellInstArray &inst, const db::CplxTrans &tr, lay::Renderer &r, unsigned int font, lay::CanvasPlane *fill, lay::CanvasPlane *contour, lay::CanvasPlane *vertex, lay::CanvasPlane *text, bool draw_outline, size_t max_shapes) { bool render_origins = false; const db::Cell &cell = layout.cell (inst.object ().cell_index ()); db::Box cell_box = cell.bbox (); db::Vector a, b; unsigned long amax = 0, bmax = 0; unsigned long long n = 1; if (inst.is_regular_array (a, b, amax, bmax)) { n = (unsigned long long) amax * (unsigned long long) bmax; } bool draw_shapes; if (max_shapes > 0) { size_t nshapes = 0; draw_shapes = true; for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers () && draw_shapes; ++l) { db::RecursiveShapeIterator shapes (layout, cell, (*l).first); while (draw_shapes && ! shapes.at_end ()) { nshapes += n; if (nshapes > max_shapes) { draw_shapes = false; } ++shapes; } } } else { draw_shapes = false; } if (draw_outline || ! draw_shapes) { if (n > 1000) { db::Vector av(a), bv(b); // fallback to simpler representation using a description text db::CplxTrans tbox (tr * inst.complex_trans ()); // one representative instance r.draw (cell_box, tbox, fill, contour, 0, text); r.draw (cell_box, db::CplxTrans (tr * (av * long (amax - 1))) * tbox, fill, contour, 0, text); r.draw (cell_box, db::CplxTrans (tr * (bv * long (bmax - 1))) * tbox, fill, contour, 0, text); r.draw (cell_box, db::CplxTrans (tr * (av * long (amax - 1) + bv * long (bmax - 1))) * tbox, fill, contour, 0, text); db::DBox cb (tbox * cell_box); db::DPolygon p; db::DPoint points[] = { db::DPoint (cb.lower_left ()), db::DPoint (cb.lower_left () + tr * (av * long (amax - 1))), db::DPoint (cb.lower_left () + tr * (av * long (amax - 1) + bv * long (bmax - 1))), db::DPoint (cb.lower_left () + tr * (bv * long (bmax - 1))), }; p.assign_hull (points, points + sizeof (points) / sizeof (points[0])); r.draw (p, fill, contour, 0, text); db::DBox arr_box (db::DPoint (), db::DPoint () + tr * (av * long (amax - 1) + bv * long (bmax - 1))); arr_box *= cb; r.draw (arr_box, tl::sprintf (tl::to_string (QObject::tr ("Array %ldx%ld")), amax, bmax), (db::Font) font, db::HAlignCenter, db::VAlignCenter, db::DFTrans (db::DFTrans::r0), 0, 0, 0, text); } else { for (db::CellInstArray::iterator arr = inst.begin (); ! arr.at_end (); ++arr) { r.draw (cell_box, tr * inst.complex_trans (*arr), fill, contour, 0, text); } render_origins = true; } } // draw the interiour of the instance if required. if (draw_shapes) { render_origins = true; for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers () && draw_shapes; ++l) { db::RecursiveShapeIterator shapes (layout, cell, (*l).first); while (! shapes.at_end ()) { for (db::CellInstArray::iterator arr = inst.begin (); ! arr.at_end (); ++arr) { r.draw (*shapes, tr * inst.complex_trans (*arr) * shapes.trans (), fill, contour, 0 /*use vertex for origin*/, text); } ++shapes; } } } // render the origins if (render_origins && vertex) { for (db::CellInstArray::iterator arr = inst.begin (); ! arr.at_end (); ++arr) { db::DPoint dp = db::DPoint () + (tr * inst.complex_trans (*arr)).disp (); r.draw (db::DEdge (dp, dp), 0, 0, vertex, 0); } } } // ------------------------------------------------------------------------ MarkerBase::MarkerBase (lay::LayoutView *view) : lay::ViewObject (view->view_object_widget ()), m_line_width (-1), m_vertex_size (-1), m_halo (-1), m_vertex_shape (lay::ViewOp::Rect), m_line_style (-1), m_dither_pattern (-1), m_frame_pattern (0), mp_view (view) { // .. nothing yet .. } void MarkerBase::set_frame_color (QColor color) { if (color != m_frame_color) { m_frame_color = color; redraw (); } } void MarkerBase::set_color (QColor color) { if (color != m_color) { m_color = color; redraw (); } } void MarkerBase::set_line_width (int lw) { if (m_line_width != lw) { m_line_width = lw; redraw (); } } void MarkerBase::set_vertex_shape (lay::ViewOp::Shape vs) { if (m_vertex_shape != vs) { m_vertex_shape = vs; redraw (); } } void MarkerBase::set_vertex_size (int vs) { if (m_vertex_size != vs) { m_vertex_size = vs; redraw (); } } void MarkerBase::set_halo (int halo) { if (m_halo != halo) { m_halo = halo; redraw (); } } void MarkerBase::set_frame_pattern (int frame_pattern) { if (m_frame_pattern != frame_pattern) { m_frame_pattern = frame_pattern; redraw (); } } void MarkerBase::set_dither_pattern (int dither_pattern) { if (m_dither_pattern != dither_pattern) { m_dither_pattern = dither_pattern; redraw (); } } void MarkerBase::set_line_style (int line_style) { if (m_line_style != line_style) { m_line_style = line_style; redraw (); } } void MarkerBase::get_bitmaps (const Viewport & /*vp*/, ViewObjectCanvas &canvas, lay::CanvasPlane *&fill, lay::CanvasPlane *&contour, lay::CanvasPlane *&vertex, lay::CanvasPlane *&text) { double resolution = canvas.resolution (); int basic_width = int(0.5 + 1.0 / resolution); // obtain bitmaps QColor color = m_color; if (! color.isValid ()) { color = mp_view->default_marker_color (); } if (! color.isValid ()) { color = canvas.foreground_color (); } QColor frame_color = m_frame_color; if (! frame_color.isValid ()) { frame_color = color; } int line_width = m_line_width < 0 ? mp_view->default_marker_line_width () : m_line_width; int vertex_size = m_vertex_size < 0 ? mp_view->default_marker_vertex_size () : m_vertex_size; bool halo = m_halo < 0 ? mp_view->default_marker_halo () : (m_halo != 0); int dither_pattern = m_dither_pattern < 0 ? mp_view->default_dither_pattern () : m_dither_pattern; int line_style = m_line_style < 0 ? mp_view->default_line_style () : m_line_style; if (halo) { std::vector ops; ops.resize (2); if (dither_pattern >= 0) { ops[0] = lay::ViewOp (canvas.background_color ().rgb (), lay::ViewOp::Copy, 0, (unsigned int) dither_pattern, 0, lay::ViewOp::Rect, 3 * basic_width, 0); ops[1] = lay::ViewOp (color.rgb (), lay::ViewOp::Copy, 0, (unsigned int) dither_pattern, 0, lay::ViewOp::Rect, basic_width, 1); fill = canvas.plane (ops); } else { fill = 0; } ops[0] = lay::ViewOp (canvas.background_color ().rgb (), lay::ViewOp::Copy, (unsigned int) line_style, (unsigned int) m_frame_pattern, 0, lay::ViewOp::Rect, line_width > 0 ? (line_width + 2) * basic_width : 0, 0); ops[1] = lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, (unsigned int) line_style, (unsigned int) m_frame_pattern, 0, lay::ViewOp::Rect, line_width * basic_width, 1); contour = canvas.plane (ops); if (line_width == 1) { text = contour; } else { ops[0] = lay::ViewOp (canvas.background_color ().rgb (), lay::ViewOp::Copy, 0, 0, 0, lay::ViewOp::Rect, 3 * basic_width, 0); ops[1] = lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, 0, 0, 0, lay::ViewOp::Rect, basic_width, 1); text = canvas.plane (ops); } if (m_vertex_shape == lay::ViewOp::Rect) { ops[0] = lay::ViewOp (canvas.background_color ().rgb (), lay::ViewOp::Copy, 0, 0, 0, m_vertex_shape, vertex_size > 0 ? (vertex_size + 2) * basic_width : 0, 0); ops[1] = lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, 0, 0, 0, m_vertex_shape, vertex_size * basic_width, 1); vertex = canvas.plane (ops); } else { std::vector ops1; ops1.resize (1); ops1[0] = lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, 0, 0, 0, m_vertex_shape, vertex_size * basic_width, 1); vertex = canvas.plane (ops1); } } else { if (dither_pattern >= 0) { fill = canvas.plane (lay::ViewOp (color.rgb (), lay::ViewOp::Copy, 0, (unsigned int) dither_pattern, 0, lay::ViewOp::Rect, basic_width)); } else { fill = 0; } contour = canvas.plane (lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, (unsigned int) line_style, (unsigned int) m_frame_pattern, 0, lay::ViewOp::Rect, line_width * basic_width)); vertex = canvas.plane (lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, 0, 0, 0, m_vertex_shape, vertex_size * basic_width)); if (line_width == 1) { text = contour; } else { text = canvas.plane (lay::ViewOp (frame_color.rgb (), lay::ViewOp::Copy, 0, 0, 0, lay::ViewOp::Rect, basic_width)); } } } // ------------------------------------------------------------------------ GenericMarkerBase::GenericMarkerBase (lay::LayoutView *view, unsigned int cv_index) : MarkerBase (view), mp_trans_vector (0), mp_view (view), m_cv_index (cv_index) { // .. nothing yet .. } GenericMarkerBase::~GenericMarkerBase () { if (mp_trans_vector) { delete mp_trans_vector; mp_trans_vector = 0; } } void GenericMarkerBase::set_trans (const db::CplxTrans &trans) { if (! m_trans.equal (trans)) { m_trans = trans; redraw (); } } void GenericMarkerBase::set (const db::ICplxTrans &t1) { if (mp_trans_vector) { delete mp_trans_vector; mp_trans_vector = 0; } m_trans = db::CplxTrans (dbu ()) * t1; redraw (); } void GenericMarkerBase::set (const db::DCplxTrans &t1) { if (mp_trans_vector) { delete mp_trans_vector; mp_trans_vector = 0; } // Note: this cast is not really correct but we handle float and integer types in the same fashion now. m_trans = db::CplxTrans (db::DCplxTrans (dbu ()) * t1); redraw (); } void GenericMarkerBase::set (const db::ICplxTrans &t1, const std::vector &trans) { if (mp_trans_vector) { delete mp_trans_vector; mp_trans_vector = 0; } if (trans.size () == 1) { m_trans = trans [0] * db::CplxTrans (dbu ()) * t1; } else { m_trans = db::CplxTrans (dbu ()) * t1; mp_trans_vector = new std::vector (trans); } redraw (); } void GenericMarkerBase::set (const db::DCplxTrans &t1, const std::vector &trans) { if (mp_trans_vector) { delete mp_trans_vector; mp_trans_vector = 0; } if (trans.size () == 1) { // Note: this cast is not really correct but we handle float and integer types in the same fashion now. m_trans = db::CplxTrans (trans [0] * db::DCplxTrans (dbu ()) * t1); } else { // Note: this cast is not really correct but we handle float and integer types in the same fashion now. m_trans = db::CplxTrans (db::DCplxTrans (dbu ()) * t1); mp_trans_vector = new std::vector (trans); } redraw (); } db::DBox GenericMarkerBase::bbox () const { const lay::CellView &cv = mp_view->cellview (m_cv_index); if (! cv.is_valid ()) { return db::DBox (); } if (mp_trans_vector) { db::DBox b; db::DBox ib = item_bbox (); for (std::vector::const_iterator t = mp_trans_vector->begin (); t != mp_trans_vector->end (); ++t) { b += (*t * db::DCplxTrans (m_trans)) * ib; } return b; } else { return db::DCplxTrans (m_trans) * item_bbox (); } } const db::Layout * GenericMarkerBase::layout () const { if (m_cv_index >= (unsigned int) (mp_view->cellviews ())) { return 0; } const lay::CellView &cv = mp_view->cellview (m_cv_index); if (! cv.is_valid ()) { return 0; } else { return &cv->layout (); } } double GenericMarkerBase::dbu () const { const db::Layout *ly = layout (); return ly ? ly->dbu () : 1.0; } // ------------------------------------------------------------------------ InstanceMarker::InstanceMarker (lay::LayoutView *view, unsigned int cv_index, bool draw_outline, size_t max_shapes) : GenericMarkerBase (view, cv_index), m_draw_outline (draw_outline), m_max_shapes (max_shapes), m_inst () { // .. nothing yet .. } InstanceMarker::~InstanceMarker () { // .. nothing yet .. } void InstanceMarker::set (const db::Instance &instance, const db::ICplxTrans &trans) { m_inst = instance; GenericMarkerBase::set (trans); } void InstanceMarker::set (const db::Instance &instance, const db::ICplxTrans &t1, const std::vector &trans) { m_inst = instance; GenericMarkerBase::set (t1, trans); } void InstanceMarker::render (const Viewport &vp, ViewObjectCanvas &canvas) { const db::Layout *ly = layout (); if (! ly) { return; } lay::CanvasPlane *fill, *contour, *vertex, *text; get_bitmaps (vp, canvas, fill, contour, vertex, text); if (contour == 0 && vertex == 0 && fill == 0 && text == 0) { return; } lay::Renderer &r = canvas.renderer (); r.set_font (db::Font (view ()->text_font ())); r.apply_text_trans (view ()->apply_text_trans ()); r.default_text_size (db::Coord (view ()->default_text_size () / ly->dbu ())); r.set_precise (true); db::box_convert bc (*ly); if (! trans_vector ()) { render_cell_inst (*ly, m_inst.cell_inst (), vp.trans () * trans (), r, view ()->cell_box_text_font (), fill, contour, vertex, text, m_draw_outline, m_max_shapes); } else { for (std::vector::const_iterator tr = trans_vector ()->begin (); tr != trans_vector ()->end (); ++tr) { render_cell_inst (*ly, m_inst.cell_inst (), vp.trans () * *tr * trans (), r, view ()->cell_box_text_font (), fill, contour, vertex, text, m_draw_outline, m_max_shapes); } } } void InstanceMarker::set_draw_outline (bool d) { if (d != m_draw_outline) { m_draw_outline = d; redraw (); } } void InstanceMarker::set_max_shapes (size_t s) { if (s != m_max_shapes) { m_max_shapes = s; redraw (); } } db::DBox InstanceMarker::item_bbox () const { return db::DBox (m_inst.bbox ()); } // ------------------------------------------------------------------------ ShapeMarker::ShapeMarker (lay::LayoutView *view, unsigned int cv_index) : GenericMarkerBase (view, cv_index), m_shape () { // .. nothing yet .. } ShapeMarker::~ShapeMarker () { // .. nothing yet .. } void ShapeMarker::set (const db::Shape &shape, const db::ICplxTrans &trans) { m_shape = shape; GenericMarkerBase::set (trans); } void ShapeMarker::set (const db::Shape &shape, const db::ICplxTrans &t1, const std::vector &trans) { m_shape = shape; GenericMarkerBase::set (t1, trans); } void ShapeMarker::render (const Viewport &vp, ViewObjectCanvas &canvas) { const db::Layout *ly = layout (); if (! ly) { return; } lay::CanvasPlane *fill, *contour, *vertex, *text; get_bitmaps (vp, canvas, fill, contour, vertex, text); if (contour == 0 && vertex == 0 && fill == 0 && text == 0) { return; } lay::Renderer &r = canvas.renderer (); r.set_font (db::Font (view ()->text_font ())); r.apply_text_trans (view ()->apply_text_trans ()); r.default_text_size (db::Coord (view ()->default_text_size () / ly->dbu ())); r.set_precise (true); if (trans_vector ()) { for (std::vector::const_iterator tr = trans_vector ()->begin (); tr != trans_vector ()->end (); ++tr) { db::CplxTrans t = vp.trans () * *tr * trans (); r.draw (m_shape, t, fill, contour, vertex, text); r.draw_propstring (m_shape, &ly->properties_repository (), text, t); } } else { db::CplxTrans t = vp.trans () * trans (); r.draw (m_shape, t, fill, contour, vertex, text); r.draw_propstring (m_shape, &ly->properties_repository (), text, t); } } db::DBox ShapeMarker::item_bbox () const { return db::DBox (m_shape.bbox ()); } // ------------------------------------------------------------------------ Marker::Marker (lay::LayoutView *view, unsigned int cv_index, bool draw_outline, size_t max_shapes) : GenericMarkerBase (view, cv_index), m_draw_outline (draw_outline), m_max_shapes (max_shapes) { m_type = None; m_object.any = 0; } Marker::~Marker () { remove_object (); } void Marker::set () { remove_object (); redraw (); } void Marker::set (const db::Box &box, const db::ICplxTrans &trans) { remove_object (); m_type = Box; m_object.box = new db::Box (box); GenericMarkerBase::set (trans); } void Marker::set (const db::DBox &box, const db::DCplxTrans &trans) { remove_object (); m_type = DBox; m_object.dbox = new db::DBox (box); GenericMarkerBase::set (trans); } void Marker::set (const db::DBox &box, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DBox; m_object.dbox = new db::DBox (box); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::Box &box, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Box; m_object.box = new db::Box (box); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::Polygon &poly, const db::ICplxTrans &trans) { remove_object (); m_type = Polygon; m_object.polygon = new db::Polygon (poly); GenericMarkerBase::set (trans); } void Marker::set (const db::Polygon &poly, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Polygon; m_object.polygon = new db::Polygon (poly); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::DPolygon &poly, const db::DCplxTrans &trans) { remove_object (); m_type = DPolygon; m_object.dpolygon = new db::DPolygon (poly); GenericMarkerBase::set (trans); } void Marker::set (const db::DPolygon &poly, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DPolygon; m_object.dpolygon = new db::DPolygon (poly); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::EdgePair &edge_pair, const db::ICplxTrans &trans) { remove_object (); m_type = EdgePair; m_object.edge_pair = new db::EdgePair (edge_pair); GenericMarkerBase::set (trans); } void Marker::set (const db::EdgePair &edge_pair, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = EdgePair; m_object.edge_pair = new db::EdgePair (edge_pair); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::DEdgePair &edge_pair, const db::DCplxTrans &trans) { remove_object (); m_type = DEdgePair; m_object.dedge_pair = new db::DEdgePair (edge_pair); GenericMarkerBase::set (trans); } void Marker::set (const db::DEdgePair &edge_pair, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DEdgePair; m_object.dedge_pair = new db::DEdgePair (edge_pair); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::Edge &edge, const db::ICplxTrans &trans) { remove_object (); m_type = Edge; m_object.edge = new db::Edge (edge); GenericMarkerBase::set (trans); } void Marker::set (const db::Edge &edge, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Edge; m_object.edge = new db::Edge (edge); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::DEdge &edge, const db::DCplxTrans &trans) { remove_object (); m_type = DEdge; m_object.dedge = new db::DEdge (edge); GenericMarkerBase::set (trans); } void Marker::set (const db::DEdge &edge, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DEdge; m_object.dedge = new db::DEdge (edge); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::Path &path, const db::ICplxTrans &trans) { remove_object (); m_type = Path; m_object.path = new db::Path (path); GenericMarkerBase::set (trans); } void Marker::set (const db::Path &path, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Path; m_object.path = new db::Path (path); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::DPath &path, const db::DCplxTrans &trans) { remove_object (); m_type = DPath; m_object.dpath = new db::DPath (path); GenericMarkerBase::set (trans); } void Marker::set (const db::DPath &path, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DPath; m_object.dpath = new db::DPath (path); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::Text &text, const db::ICplxTrans &trans) { remove_object (); m_type = Text; m_object.text = new db::Text (text); GenericMarkerBase::set (trans); } void Marker::set (const db::Text &text, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Text; m_object.text = new db::Text (text); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::DText &text, const db::DCplxTrans &trans) { remove_object (); m_type = DText; m_object.dtext = new db::DText (text); GenericMarkerBase::set (trans); } void Marker::set (const db::DText &text, const db::DCplxTrans &t1, const std::vector &trans) { remove_object (); m_type = DText; m_object.dtext = new db::DText (text); GenericMarkerBase::set (t1, trans); } void Marker::set (const db::CellInstArray &instance, const db::ICplxTrans &trans) { remove_object (); m_type = Instance; m_object.inst = new db::CellInstArray (instance); GenericMarkerBase::set (trans); } void Marker::set (const db::CellInstArray &instance, const db::ICplxTrans &t1, const std::vector &trans) { remove_object (); m_type = Instance; m_object.inst = new db::CellInstArray (instance); GenericMarkerBase::set (t1, trans); } void Marker::set_draw_outline (bool d) { if (d != m_draw_outline) { m_draw_outline = d; redraw (); } } void Marker::set_max_shapes (size_t s) { if (s != m_max_shapes) { m_max_shapes = s; redraw (); } } db::DBox Marker::item_bbox () const { if (m_type == Box) { return db::DBox (*m_object.box); } else if (m_type == DBox) { return *m_object.dbox; } else if (m_type == Polygon) { return db::DBox (m_object.polygon->box ()); } else if (m_type == DPolygon) { return m_object.dpolygon->box (); } else if (m_type == EdgePair) { return db::DBox (m_object.edge_pair->bbox ()); } else if (m_type == DEdgePair) { return m_object.dedge_pair->bbox (); } else if (m_type == Edge) { return db::DBox (m_object.edge->bbox ()); } else if (m_type == DEdge) { return m_object.dedge->bbox (); } else if (m_type == Path) { return db::DBox (m_object.path->box ()); } else if (m_type == DPath) { return m_object.dpath->box (); } else if (m_type == Text) { return db::DBox (m_object.text->box ()); } else if (m_type == DText) { return m_object.dtext->box (); } else if (m_type == Instance) { const db::Layout *ly = layout (); if (ly) { return db::DBox (m_object.inst->bbox (db::box_convert (*ly))); } } return db::DBox (); } void Marker::remove_object () { if (m_type == Box) { delete m_object.box; } else if (m_type == DBox) { delete m_object.dbox; } else if (m_type == Polygon) { delete m_object.polygon; } else if (m_type == DPolygon) { delete m_object.dpolygon; } else if (m_type == EdgePair) { delete m_object.edge_pair; } else if (m_type == DEdgePair) { delete m_object.dedge_pair; } else if (m_type == Edge) { delete m_object.edge; } else if (m_type == DEdge) { delete m_object.dedge; } else if (m_type == Path) { delete m_object.path; } else if (m_type == DPath) { delete m_object.dpath; } else if (m_type == Text) { delete m_object.text; } else if (m_type == DText) { delete m_object.dtext; } else if (m_type == Instance) { delete m_object.inst; } m_type = None; m_object.any = 0; } void Marker::draw (lay::Renderer &r, const db::CplxTrans &t, lay::CanvasPlane *fill, lay::CanvasPlane *contour, lay::CanvasPlane *vertex, lay::CanvasPlane *text) { if (m_type == Box) { r.draw (*m_object.box, t, fill, contour, vertex, text); } else if (m_type == DBox) { r.draw (*m_object.dbox, db::DCplxTrans (t), fill, contour, vertex, text); } else if (m_type == Polygon) { r.draw (*m_object.polygon, t, fill, contour, vertex, text); } else if (m_type == DPolygon) { r.draw (*m_object.dpolygon, db::DCplxTrans (t), fill, contour, vertex, text); } else if (m_type == Path) { r.draw (*m_object.path, t, fill, contour, vertex, text); } else if (m_type == DPath) { r.draw (*m_object.dpath, db::DCplxTrans (t), fill, contour, vertex, text); } else if (m_type == Text) { r.draw (*m_object.text, t, fill, contour, vertex, text); } else if (m_type == DText) { r.draw (*m_object.dtext, db::DCplxTrans (t), fill, contour, vertex, text); } else if (m_type == Edge) { r.draw (*m_object.edge, t, fill, contour, vertex, text); } else if (m_type == DEdge) { r.draw (*m_object.dedge, db::DCplxTrans (t), fill, contour, vertex, text); } else if (m_type == EdgePair) { r.draw (m_object.edge_pair->first (), t, fill, contour, vertex, text); r.draw (m_object.edge_pair->second (), t, fill, contour, vertex, text); db::Polygon poly = m_object.edge_pair->normalized ().to_polygon (0); r.draw (poly, t, fill, 0, 0, 0); } else if (m_type == DEdgePair) { r.draw (m_object.dedge_pair->first (), db::DCplxTrans (t), fill, contour, vertex, text); r.draw (m_object.dedge_pair->second (), db::DCplxTrans (t), fill, contour, vertex, text); db::DPolygon poly = m_object.dedge_pair->normalized ().to_polygon (0); r.draw (poly, db::DCplxTrans (t), fill, 0, 0, 0); } else if (m_type == Instance) { const lay::CellView &cv = view ()->cellview (cv_index ()); render_cell_inst (cv->layout (), *m_object.inst, t, r, view ()->cell_box_text_font (), fill, contour, vertex, text, m_draw_outline, m_max_shapes); } } void Marker::render (const Viewport &vp, ViewObjectCanvas &canvas) { lay::CanvasPlane *fill, *contour, *vertex, *text; get_bitmaps (vp, canvas, fill, contour, vertex, text); if (contour == 0 && vertex == 0 && fill == 0 && text == 0) { return; } lay::Renderer &r = canvas.renderer (); r.set_font (db::Font (view ()->text_font ())); r.apply_text_trans (view ()->apply_text_trans ()); r.default_text_size (db::Coord (view ()->default_text_size () / dbu ())); r.set_precise (true); if (! trans_vector ()) { db::CplxTrans t = vp.trans () * trans (); draw (r, t, fill, contour, vertex, text); } else { for (std::vector::const_iterator tr = trans_vector ()->begin (); tr != trans_vector ()->end (); ++tr) { db::CplxTrans t = vp.trans () * *tr * trans (); draw (r, t, fill, contour, vertex, text); } } } // ------------------------------------------------------------------------ DMarker::DMarker (lay::LayoutView *view) : MarkerBase (view), mp_view (view) { m_type = None; m_object.any = 0; } DMarker::~DMarker () { remove_object (); } void DMarker::set (const db::DBox &box) { remove_object (); m_type = Box; m_object.box = new db::DBox (box); redraw (); } void DMarker::set (const db::DPolygon &poly) { remove_object (); m_type = Polygon; m_object.polygon = new db::DPolygon (poly); redraw (); } void DMarker::set (const db::DEdgePair &edge_pair) { remove_object (); m_type = EdgePair; m_object.edge_pair = new db::DEdgePair (edge_pair); redraw (); } void DMarker::set (const db::DEdge &edge) { remove_object (); m_type = Edge; m_object.edge = new db::DEdge (edge); redraw (); } void DMarker::set (const db::DPath &path) { remove_object (); m_type = Path; m_object.path = new db::DPath (path); redraw (); } void DMarker::set (const db::DText &text) { remove_object (); m_type = Text; m_object.text = new db::DText (text); redraw (); } db::DBox DMarker::bbox () const { if (m_type == Box) { return *m_object.box; } else if (m_type == Polygon) { return m_object.polygon->box (); } else if (m_type == Edge) { return m_object.edge->bbox (); } else if (m_type == EdgePair) { return m_object.edge_pair->bbox (); } else if (m_type == Path) { return m_object.path->box (); } else if (m_type == Text) { return m_object.text->box (); } else { return db::DBox (); } } void DMarker::remove_object () { if (m_type == Box) { delete m_object.box; } else if (m_type == Polygon) { delete m_object.polygon; } else if (m_type == Edge) { delete m_object.edge; } else if (m_type == EdgePair) { delete m_object.edge_pair; } else if (m_type == Path) { delete m_object.path; } else if (m_type == Text) { delete m_object.text; } m_type = None; m_object.any = 0; } void DMarker::render (const Viewport &vp, ViewObjectCanvas &canvas) { lay::CanvasPlane *fill, *contour, *vertex, *text; get_bitmaps (vp, canvas, fill, contour, vertex, text); if (contour == 0 && vertex == 0 && fill == 0 && text == 0) { return; } lay::Renderer &r = canvas.renderer (); r.set_font (db::Font (mp_view->text_font ())); r.apply_text_trans (mp_view->apply_text_trans ()); r.default_text_size (mp_view->default_text_size ()); r.set_precise (true); db::DCplxTrans t = vp.trans (); if (m_type == Box) { r.draw (*m_object.box, t, fill, contour, vertex, text); } else if (m_type == Polygon) { r.draw (*m_object.polygon, t, fill, contour, vertex, text); } else if (m_type == Path) { r.draw (*m_object.path, t, fill, contour, vertex, text); } else if (m_type == Text) { r.draw (*m_object.text, t, fill, contour, vertex, text); } else if (m_type == Edge) { r.draw (*m_object.edge, t, fill, contour, vertex, text); } else if (m_type == EdgePair) { r.draw (m_object.edge_pair->first (), t, fill, contour, vertex, text); r.draw (m_object.edge_pair->second (), t, fill, contour, vertex, text); db::DPolygon poly = m_object.edge_pair->normalized ().to_polygon (0); r.draw (poly, t, fill, 0, 0, 0); } } }