diff --git a/crlcore/src/ccore/crlcore/Gds.h b/crlcore/src/ccore/crlcore/Gds.h index f5a24f6e..5ad386aa 100644 --- a/crlcore/src/ccore/crlcore/Gds.h +++ b/crlcore/src/ccore/crlcore/Gds.h @@ -31,13 +31,20 @@ namespace CRL { class Gds { public: - static const uint32_t NoGdsPrefix = (1<<0); - static const uint32_t Layer_0_IsBoundary = (1<<1); - static const uint32_t NoBlockages = (1<<2); + static const uint32_t NoGdsPrefix = (1<<0); + static const uint32_t Layer_0_IsBoundary = (1<<1); + static const uint32_t NoBlockages = (1<<2); + static std::string _topCellName; public: - static bool save ( Cell* ); - static bool load ( Library*, std::string gdsPath, uint32_t flags=0 ); + static bool save ( Cell* ); + static bool load ( Library*, std::string gdsPath, uint32_t flags=0 ); + inline static void setTopCellName ( std::string ); + inline static std::string getTopCellName (); }; + + inline void Gds::setTopCellName ( std::string topCellName ) { _topCellName=topCellName; } + inline std::string Gds::getTopCellName () { return _topCellName; } + } // CRL namespace. diff --git a/crlcore/src/ccore/gds/GdsParser.cpp b/crlcore/src/ccore/gds/GdsParser.cpp index 9f37b912..20afc4b9 100644 --- a/crlcore/src/ccore/gds/GdsParser.cpp +++ b/crlcore/src/ccore/gds/GdsParser.cpp @@ -37,6 +37,7 @@ using namespace std; #include "hurricane/Diagonal.h" #include "hurricane/Rectilinear.h" #include "hurricane/Pad.h" +#include "hurricane/Text.h" #include "hurricane/Net.h" #include "hurricane/Cell.h" #include "hurricane/Library.h" @@ -645,40 +646,41 @@ namespace { class GdsStream { public: - static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype ); - public: - static void _staticInit (); - GdsStream ( string gdsPath, uint32_t flags ); - inline bool useGdsPrefix () const; - inline bool useLayer0AsBoundary () const; - inline bool isValidSyntax () const; - bool misplacedRecord (); - inline void resetStrans (); - bool read ( Library* ); - bool readFormatType (); - bool readStructure (); - const Layer* readLayerAndDatatype (); - bool readBoundary (); - bool readPath (); - bool readSref (); - bool readAref (); - bool readNode (); - bool readBox (); - bool readText (); - bool readTextbody ( const Layer* ); - bool readStrans (); - bool readProperty (); - void xyToAbutmentBox (); - void xyToComponent ( const Layer* ); - void xyToPath ( uint16_t pathtype - , const Layer* - , DbU::Unit width - , DbU::Unit bgnextn - , DbU::Unit endextn ); - void makeInstances (); - void makeExternals (); - Net* fusedNet (); - void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y ); + static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype ); + public: + static void _staticInit (); + GdsStream ( string gdsPath, uint32_t flags ); + Cell* getCell ( string cellName, bool create=false ); + inline bool useGdsPrefix () const; + inline bool useLayer0AsBoundary () const; + inline bool isValidSyntax () const; + bool misplacedRecord (); + inline void resetStrans (); + bool read ( Library* ); + bool readFormatType (); + bool readStructure (); + const Layer* readLayerAndDatatype (); + bool readBoundary (); + bool readPath (); + bool readSref (); + bool readAref (); + bool readNode (); + bool readBox (); + bool readText (); + bool readTextbody ( const Layer* ); + bool readStrans (); + bool readProperty (); + void xyToAbutmentBox (); + void xyToComponent ( const Layer* ); + void xyToPath ( uint16_t pathtype + , const Layer* + , DbU::Unit width + , DbU::Unit bgnextn + , DbU::Unit endextn ); + void makeInstances (); + void makeExternals (); + Net* fusedNet (); + void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y ); private: struct DelayedInstance { inline DelayedInstance ( Cell* owner, string masterName, const Transformation& ); @@ -800,6 +802,34 @@ namespace { } + Cell* GdsStream::getCell ( string cellName, bool create ) + { + if (not _library) return nullptr; + Library* workLibrary = _library; + Cell* cell = workLibrary->getCell( cellName ); + if (cell) return cell; + + if (not Gds::getTopCellName().empty() and (cellName != Gds::getTopCellName())) { + workLibrary = _library->getLibrary( Gds::getTopCellName() ); + if (workLibrary) { + cell = workLibrary->getCell( cellName ); + if (cell) return cell; + } else { + if (not create) return nullptr; + workLibrary = Library::create( _library, Gds::getTopCellName() ); + } + } + + if (not create) return nullptr; + + cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)." + , cellName.c_str() + , getString(_library).c_str() + ) << endl; + return Cell::create( workLibrary, cellName ); + } + + bool GdsStream::misplacedRecord () { cerr << Error( "GdsStream: Misplaced record %s.\n" @@ -900,17 +930,9 @@ namespace { if (_record.isSTRNAME()) { if (_library) { string cellName = _record.getName(); - if (useGdsPrefix()) cellName.insert( 0, "gds_" ); - _cell = _library->getCell( cellName ); - if (not _cell) { - cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)." - , cellName.c_str() - , getString(_library).c_str() - ) << endl; - _cell = Cell::create( _library, cellName ); - } + _cell = getCell( cellName, true ); + _stream >> _record; } - _stream >> _record; } if (_record.isSTRCLASS()) { _stream >> _record; } @@ -1075,15 +1097,25 @@ namespace { } if (not _text.empty()) { - Net* net = _cell->getNet( _text ); - if (not net) { - net = Net::create( _cell, _text ); - net->setExternal( true ); - if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER ); - if (_text.substr(0,3) == "gnd") net->setType ( Net::Type::GROUND ); - if (_text[ _text.size()-1 ] == '!') net->setGlobal( true ); + if (static_cast(layer)->getMaterial() != BasicLayer::Material::other) { + Net* net = _cell->getNet( _text ); + if (not net) { + net = Net::create( _cell, _text ); + net->setExternal( true ); + if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER ); + if (_text.substr(0,3) == "gnd") net->setType ( Net::Type::GROUND ); + if (_text[ _text.size()-1 ] == '!') net->setGlobal( true ); + } + addNetReference( net, layer, xpos, ypos ); + } else { + DbU::Unit textHeight = _scale * 500; + DbU::Unit textWidth = _scale * 500 * _text.size(); + Text::create( _cell, layer, Box( xpos + , ypos + , xpos + textWidth + , ypos + textHeight + ), _text ); } - addNetReference( net, layer, xpos, ypos ); } cdebug_log(101,-1) << "GdsStream::readTextbody() - return:" << _validSyntax << endl; @@ -1260,7 +1292,6 @@ namespace { // << " XR:" << _xReflection << " angle:" << _angle // << " " << Transformation(xpos,ypos,orient) // << " in " << _cell << endl; - if (useGdsPrefix()) masterName.insert( 0, "gds_" ); _delayedInstances.push_back( DelayedInstance( _cell , masterName , Transformation(xpos,ypos,orient)) ); @@ -1698,7 +1729,7 @@ namespace { cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl; for ( const DelayedInstance& di : _delayedInstances ) { - Cell* masterCell = _library->getCell( di._masterName ); + Cell* masterCell = getCell( di._masterName ); if (masterCell) { string insName = "sref_" + getString(_SREFCount++); @@ -1710,6 +1741,9 @@ namespace { , Instance::PlacementStatus::FIXED ); cdebug_log(101,0) << "| " << instance << " @" << di._transformation << " in " << di._owner << endl; + } else { + cerr << Error( "GdsStream::makeInstances(): Delayed sub-model (STRUCTURE) \"%s\" not found." + , di._masterName.c_str() ) << endl; } } cdebug_tabw(101,-1); @@ -1840,6 +1874,10 @@ namespace CRL { // ------------------------------------------------------------------- // Class : "CRL::Gds". + + std::string Gds::_topCellName = ""; + + bool Gds::load ( Library* library, string gdsPath, uint32_t flags ) { //DebugSession::open( 101, 110 ); @@ -1856,6 +1894,7 @@ namespace CRL { Contact::enableCheckMinSize(); UpdateSession::close(); + Gds::setTopCellName( "" ); //DebugSession::close(); return true; diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp index 199d1aa6..e0ed3cc0 100644 --- a/crlcore/src/ccore/lefdef/LefImport.cpp +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -357,7 +357,9 @@ namespace { if (not _cell) { if (name.empty()) name = "EarlyLEFCell"; - _cell = Cell::create( getLibrary(true), name ); + _cell = getLibrary(true)->getCell( name ); + if (not _cell) + _cell = Cell::create( getLibrary(true), name ); } return _cell; } @@ -533,20 +535,25 @@ namespace { { LefParser* parser = (LefParser*)ud; - if (_gdsForeignDirectory.empty()) { - cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl; - return 0; + Cell* cell = parser->earlyGetCell( foreign->cellName() ); + + if (cell->getName() == "EarlyLEFCell") { + if (_gdsForeignDirectory.empty()) { + cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl; + return 0; + } + + string gdsPath = _gdsForeignDirectory + "/" + foreign->cellName() + ".gds"; + parser->setForeignPath( gdsPath ); + + Gds::setTopCellName( foreign->cellName() ); + Gds::load( parser->getLibrary(), parser->getForeignPath() + , Gds::NoBlockages|Gds::Layer_0_IsBoundary); } - string gdsPath = _gdsForeignDirectory + "/" + foreign->cellName() + ".gds"; - parser->setForeignPath( gdsPath ); parser->setForeignPosition( Point( parser->fromUnitsMicrons( foreign->px() ) , parser->fromUnitsMicrons( foreign->px() ))); - Cell* cell = parser->earlyGetCell( foreign->cellName() ); - - Gds::load( parser->getLibrary(), parser->getForeignPath() - , Gds::NoGdsPrefix|Gds::NoBlockages|Gds::Layer_0_IsBoundary); for ( Net* net : cell->getNets() ) { if (net->isPower ()) parser->setGdsPower ( net ); if (net->isGround()) parser->setGdsGround( net ); diff --git a/crlcore/src/pyCRL/PyGds.cpp b/crlcore/src/pyCRL/PyGds.cpp index 1e2d7270..b7e4c440 100644 --- a/crlcore/src/pyCRL/PyGds.cpp +++ b/crlcore/src/pyCRL/PyGds.cpp @@ -63,7 +63,6 @@ extern "C" { static PyObject* PyGds_save ( PyObject*, PyObject* args ) { cdebug_log(30,0) << "PyGds_save()" << endl; - HTRY PyObject* pyCell = NULL; if (PyArg_ParseTuple( args, "O:Gds.save", &pyCell )) { @@ -78,7 +77,6 @@ extern "C" { return NULL; } HCATCH - Py_RETURN_NONE; } @@ -86,10 +84,8 @@ extern "C" { static PyObject* PyGds_load ( PyObject*, PyObject* args ) { cdebug_log(30,0) << "PyGds_load()" << endl; - char* path = NULL; uint32_t flags = 0; - HTRY PyObject* pyLibrary = NULL; if (PyArg_ParseTuple( args, "Os|I:Gds.load", &pyLibrary, &path, &flags )) { @@ -104,7 +100,23 @@ extern "C" { return NULL; } HCATCH + Py_RETURN_NONE; + } + + static PyObject* PyGds_setTopCellName ( PyObject*, PyObject* args ) + { + cdebug_log(30,0) << "PyGds_setTopCellName()" << endl; + char* topCellName = NULL; + HTRY + PyObject* pyLibrary = NULL; + if (PyArg_ParseTuple( args, "s:Gds.setTopCellName", &topCellName )) { + Gds::setTopCellName( string(topCellName) ); + } else { + PyErr_SetString( ConstructorError, "Gds.setTopCellName(): Takes *one* str argument only." ); + return NULL; + } + HCATCH Py_RETURN_NONE; } @@ -113,10 +125,12 @@ extern "C" { PyMethodDef PyGds_Methods[] = - { { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC + { { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC , "Save a complete Gds design." } - , { "load" , (PyCFunction)PyGds_load , METH_VARARGS|METH_STATIC + , { "load" , (PyCFunction)PyGds_load , METH_VARARGS|METH_STATIC , "Load a Gds layout inside a Cell (cumulative)." } + , { "setTopCellName" , (PyCFunction)PyGds_setTopCellName, METH_VARARGS|METH_STATIC + , "The name of the main cell from the GDS (not to be renamed)." } , {NULL, NULL, 0, NULL} /* sentinel */ }; @@ -140,6 +154,7 @@ extern "C" { { PyObject* constant; LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoGdsPrefix ,"NoGdsPrefix"); + LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoBlockages ,"NoBlockages"); LoadObjectConstant(PyTypeGds.tp_dict,Gds::Layer_0_IsBoundary,"Layer_0_IsBoundary"); } diff --git a/hurricane/src/hurricane/CMakeLists.txt b/hurricane/src/hurricane/CMakeLists.txt index ca6e22a8..d60e9198 100644 --- a/hurricane/src/hurricane/CMakeLists.txt +++ b/hurricane/src/hurricane/CMakeLists.txt @@ -44,6 +44,7 @@ hurricane/Filter.h hurricane/Go.h hurricane/Gos.h hurricane/ExtensionGo.h hurricane/ExtensionGos.h + hurricane/Text.h hurricane/Hook.h hurricane/Hooks.h hurricane/Horizontal.h hurricane/Horizontals.h hurricane/HyperNet.h @@ -163,6 +164,7 @@ DeepNet.cpp HyperNet.cpp Go.cpp + Text.cpp ExtensionGo.cpp Hook.cpp Instance.cpp diff --git a/hurricane/src/hurricane/Instance.cpp b/hurricane/src/hurricane/Instance.cpp index 9997e585..ad8f03ef 100644 --- a/hurricane/src/hurricane/Instance.cpp +++ b/hurricane/src/hurricane/Instance.cpp @@ -204,7 +204,7 @@ Instance::Instance(Cell* cell, const Name& name, Cell* masterCell, const Transfo throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", empty name"); if (_cell->getInstance(_name)) - throw Error("Instance::Instance(): Can't create " + _TName("Instance") + " " + getString(_name) + ", already exists"); + throw Error("Instance::Instance(): Can't create " + _TName("Instance") + " " + getString(_name) + ", already exists in " + getString(cell) ); if (!_masterCell) throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", NULL master cell"); diff --git a/hurricane/src/hurricane/Text.cpp b/hurricane/src/hurricane/Text.cpp new file mode 100644 index 00000000..8848b1dc --- /dev/null +++ b/hurricane/src/hurricane/Text.cpp @@ -0,0 +1,169 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Text.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Slice.h" +#include "hurricane/Text.h" +#include "hurricane/Net.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Layer.h" +#include "hurricane/Cell.h" +#include "hurricane/Error.h" +#include "hurricane/Warning.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "Text". + + Text::Text ( Cell* cell, const Layer* layer, const Box& boundingBox, std::string text ) + : Super () + , _cell (cell) + , _layer (layer) + , _boundingBox(boundingBox) + , _text (text) + { } + + + Text* Text::create ( Cell* cell, const Layer* layer, const Box& boundingBox, std::string text ) + { + if (not layer) + throw Error( "Text::create(): Can't create, NULL layer" ); + + Text* goText = new Text ( cell, layer, boundingBox, text ); + goText->_postCreate(); + + return goText; + } + + + + + Cell* Text::getCell () const { return _cell; } + const Layer* Text::getLayer () const { return _layer; } + DbU::Unit Text::getX () const { return getBoundingBox().getCenter().getX(); } + DbU::Unit Text::getY () const { return getBoundingBox().getCenter().getY(); } + + + Box Text::getBoundingBox() const + { return _boundingBox; } + + + Box Text::getBoundingBox ( const BasicLayer* basicLayer ) const + { + if (not _layer->contains(basicLayer)) return Box(); + return getBoundingBox(); + } + + + void Text::translate ( const DbU::Unit& dx, const DbU::Unit& dy ) + { + if ( (dx != 0) or (dy != 0) ) { + invalidate( true ); + _boundingBox.translate( dx, dy ); + } + } + + + void Text::setLayer ( const Layer* layer ) + { + if (not layer) throw Error( "Text::setLayer(): Can't set layer, NULL layer" ); + + if (layer != _layer) { + invalidate( false ); + _layer = layer; + } + } + + + void Text::materialize() + { + cdebug_log(18,0) << "Text::materialize() - " << this << endl; + + if (isMaterialized()) return; + + Cell* cell = getCell(); + const Layer* layer = getLayer(); + if (not cell or not layer) return; + + Slice* slice = cell->getSlice( layer ); + if (not slice) slice = Slice::_create( cell, layer ); + QuadTree* quadTree = slice->_getQuadTree(); + quadTree->insert( this ); + cell->_fit( quadTree->getBoundingBox() ); + } + + + void Text::unmaterialize() + { + cdebug_log(18,0) << "Text::unmaterialize() " << this << endl; + + if (not isMaterialized()) return; + Cell* cell = getCell(); + Slice* slice = cell->getSlice(getLayer()); + if (not slice) return; + + cell->_unfit(getBoundingBox()); + slice->_getQuadTree()->remove(this); + if (slice->isEmpty()) slice->_destroy(); + } + + string Text::_getTypeName () const + { return _TName( "Text" ); } + + + string Text::_getString () const + { + string s = Super::_getString(); + s.insert( s.length() - 1, " " + getString(_layer->getName()) ); + s.insert( s.length() - 1, " \"" + _text + "\"" ); + s.insert( s.length() - 1, " @" + getString(_boundingBox) ); + return s; + } + + + Record* Text::_getRecord () const + { + Record* record = Super::_getRecord(); + if (record) { + record->add( getSlot("_cell" , _cell ) ); + record->add( getSlot("_layer" , _layer ) ); + record->add( getSlot("_boundinBox", &_boundingBox) ); + record->add( getSlot("_text" , _text ) ); + } + return record; + } + + +} // Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Text.h b/hurricane/src/hurricane/hurricane/Text.h new file mode 100644 index 00000000..a9b96004 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/Text.h @@ -0,0 +1,83 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2018-2023, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/Text.h" | +// +-----------------------------------------------------------------+ + +#pragma once +#include "hurricane/Component.h" + + +namespace Hurricane { + + class Layer; + + +// ------------------------------------------------------------------- +// Class : "Text". + + class Text : public Go { + public: + typedef Go Super; + + public: + static Text* create ( Cell*, const Layer*, const Box&, std::string ); + // Accessors. + virtual Cell* getCell () const; + virtual DbU::Unit getX () const; + virtual DbU::Unit getY () const; + virtual Box getBoundingBox () const; + virtual Box getBoundingBox ( const BasicLayer* ) const; + inline std::string getText () const; + // Mutators. + void setLayer ( const Layer* ); + const Layer* getLayer () const; + virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); + virtual void materialize (); + virtual void unmaterialize (); + // Hurricane management. + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + Text ( Cell*, const Layer*, const Box&, std::string ); + private: + Cell* _cell; + const Layer* _layer; + Box _boundingBox; + std::string _text; + + }; + + + inline std::string Text::getText () const { return _text; } + + +} // Hurricane namespace. + + +INSPECTOR_P_SUPPORT(Hurricane::Text); diff --git a/hurricane/src/viewer/CellWidget.cpp b/hurricane/src/viewer/CellWidget.cpp index 8cd3c6f8..b09bafb9 100644 --- a/hurricane/src/viewer/CellWidget.cpp +++ b/hurricane/src/viewer/CellWidget.cpp @@ -45,6 +45,7 @@ #include "hurricane/Polygon.h" #include "hurricane/RoutingPad.h" #include "hurricane/ExtensionGo.h" +#include "hurricane/Text.h" #include "hurricane/viewer/Graphics.h" #include "hurricane/viewer/PaletteItem.h" @@ -721,6 +722,18 @@ namespace Hurricane { _cellWidget->drawDisplayText( rectangle, netName, BigFont|Bold|Center|Frame ); } } + + return; + } + + const Text* text = dynamic_cast(go); + if (text) { + _goCount++; + Box bb = transformation.getBox(text->getBoundingBox(basicLayer)); + rectangle = _cellWidget->dbuToScreenRect( bb ); + if ((rectangle.width() < 5) or (rectangle.height() < 5)) + return; + _cellWidget->drawDisplayText( rectangle, text->getText().c_str(), FillBox|Left ); } } @@ -1388,7 +1401,6 @@ namespace Hurricane { for ( BasicLayer* layer : _technology->getBasicLayers() ) { _drawingPlanes.setPen ( Graphics::getPen (layer->getName(),getDarkening()) ); _drawingPlanes.setBrush( Graphics::getBrush(layer->getName(),getDarkening()) ); - if ( isDrawable(layer->getName()) ) { _drawingQuery.setBasicLayer( layer ); _drawingQuery.setFilter ( getQueryFilter().unset(Query::DoMasterCells @@ -1698,67 +1710,84 @@ namespace Hurricane { void CellWidget::drawDisplayText ( const QRect& box, const char* text, unsigned int flags ) { - QFont font = Graphics::getNormalFont(flags&Bold); + shared_ptr font = shared_ptr( new QFont( Graphics::getNormalFont( flags&Bold ))); - if ( flags & BigFont ) font.setPointSize ( Graphics::isHighDpi() ? 7 : 18 ); + if (flags & BigFont) + font->setPointSize( Graphics::isHighDpi() ? 7 : 18 ); + if (flags & FillBox) { + QFontMetrics metrics = QFontMetrics( *font ); + float width = (float)metrics.width( text ); + float ptSize = font->pointSizeF(); + ptSize *= ((float)box.width() / width); + font->setPointSizeF( ptSize ); + } - QFontMetrics metrics = QFontMetrics(font); + QFontMetrics metrics = QFontMetrics( *font ); int width = metrics.width( text ); - //int height = metrics.height (); + //int height = metrics.height(); int angle = 0; if ( (width > box.width()) and (box.height() > 2*box.width()) ) angle = -90; - drawDisplayText ( box.center(), text, flags, angle ); + QPoint textBL ( box.center() ); + if (flags & Top) { + textBL.ry() += box.height() / 2; + } + if (flags & Left) { + textBL.rx() -= box.width() / 2; + } + + drawDisplayText( textBL, text, flags, angle, font ); } - void CellWidget::drawDisplayText ( const QPoint& point, const char* text, unsigned int flags, int angle ) + void CellWidget::drawDisplayText ( const QPoint& point, const char* text, unsigned int flags, int angle, shared_ptr font ) { - QPainter& painter = _drawingPlanes.painter(); - QPen pen = painter.pen (); - QBrush brush = painter.brush (); - QFont font = Graphics::getNormalFont(flags&Bold); + QPainter& painter = _drawingPlanes.painter(); + QPen pen = painter.pen(); + QBrush brush = painter.brush(); + + if (not font.get()) + font = shared_ptr( new QFont( Graphics::getNormalFont( flags&Bold ))); painter.save(); - if ( flags & Reverse ) painter.setPen ( Graphics::getPen("background") ); - if ( flags & Reverse ) painter.setBackgroundMode ( Qt::OpaqueMode ); - if ( flags & BigFont ) font.setPointSize ( Graphics::isHighDpi() ? 7 : 18 ); + if (flags & Reverse) painter.setPen( Graphics::getPen("background") ); + if (flags & Reverse) painter.setBackgroundMode( Qt::OpaqueMode ); - QFontMetrics metrics = QFontMetrics(font); - int width = metrics.width ( text ); - int height = metrics.height (); + QFontMetrics metrics = QFontMetrics ( *font ); + int width = metrics.width ( text ); + int height = metrics.height(); - pen.setStyle ( Qt::SolidLine ); - pen.setColor ( painter.brush().color() ); + pen.setStyle( Qt::SolidLine ); + pen.setColor( painter.brush().color() ); - brush.setStyle ( Qt::NoBrush ); + brush.setStyle( Qt::NoBrush ); - painter.setPen ( pen ); - painter.setBrush ( brush ); - painter.setFont ( font ); - painter.translate ( point ); - painter.rotate ( angle ); + painter.setPen ( pen ); + painter.setBrush ( brush ); + painter.setFont ( *font ); + painter.translate( point ); + painter.rotate ( angle ); QPoint bottomLeft ( 0, 0); - if ( flags & Center ) { + if (flags & Center) { bottomLeft.rx() -= width /2; bottomLeft.ry() += height/2; - } else if ( flags & Top ) { + } else if (flags & Top) { bottomLeft.ry() += height; - } else if ( flags & Left ) { + } else if (flags & Left) { } - if ( flags & Frame ) { - if ( flags & Rounded ) - painter.drawRoundedRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 ); + if (flags & Frame) { + if (flags & Rounded) + painter.drawRoundedRect( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 ); else - painter.drawRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height ); + painter.drawRect( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height ); } - painter.drawText ( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text ); - painter.restore (); + painter.drawText( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text ); + painter.restore (); } diff --git a/hurricane/src/viewer/hurricane/viewer/CellWidget.h b/hurricane/src/viewer/hurricane/viewer/CellWidget.h index 3abd74f1..13ae2c4d 100644 --- a/hurricane/src/viewer/hurricane/viewer/CellWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/CellWidget.h @@ -104,6 +104,7 @@ namespace Hurricane { , Left =0x0040 , Right =0x0080 , Top =0x0100 + , FillBox =0x0200 }; enum Flag { NoFlags =0x0000 , NoResetCommands=0x0001 @@ -193,7 +194,7 @@ namespace Hurricane { void drawRuler ( shared_ptr ); void drawRulers ( QRect ); void drawDisplayText ( const QRect& , const char*, unsigned int flags=0 ); - void drawDisplayText ( const QPoint&, const char*, unsigned int flags=0, int angle=0 ); + void drawDisplayText ( const QPoint&, const char*, unsigned int flags=0, int angle=0, std::shared_ptr font=std::shared_ptr() ); void drawScreenPolygon ( const QPoint*, int count, size_t plane=PlaneId::Working ); void drawScreenPolygon ( const QPolygon&, size_t plane=PlaneId::Working ); void drawScreenLine ( const QPoint&, const QPoint&, size_t plane=PlaneId::Working, bool mode=true );