diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2019-09-10 20:19:09 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2019-09-10 20:19:09 (GMT) |
commit | cc4253926526efc87385de9640e64cd5cf062ada (patch) | |
tree | 3bddf87f17e99be18dfcd24d460b9e4f264964bc /src | |
parent | 81da20ff839843634ee6db5f517bfcb7ef87d4b9 (diff) | |
download | Doxygen-cc4253926526efc87385de9640e64cd5cf062ada.zip Doxygen-cc4253926526efc87385de9640e64cd5cf062ada.tar.gz Doxygen-cc4253926526efc87385de9640e64cd5cf062ada.tar.bz2 |
Refactoring code for dot related source files
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/configimpl.l | 27 | ||||
-rw-r--r-- | src/dot.cpp | 273 | ||||
-rw-r--r-- | src/dot.h | 43 | ||||
-rw-r--r-- | src/dotdirdeps.cpp | 8 | ||||
-rw-r--r-- | src/dotfilepatcher.cpp | 152 | ||||
-rw-r--r-- | src/dotfilepatcher.h | 21 | ||||
-rw-r--r-- | src/dotgraph.cpp | 101 | ||||
-rw-r--r-- | src/dotgraph.h | 9 | ||||
-rw-r--r-- | src/dotgroupcollaboration.cpp | 11 | ||||
-rw-r--r-- | src/dotlegendgraph.cpp | 72 | ||||
-rw-r--r-- | src/dotlegendgraph.h | 35 | ||||
-rw-r--r-- | src/dotnode.cpp | 4 | ||||
-rw-r--r-- | src/dotrunner.cpp | 18 | ||||
-rw-r--r-- | src/dotrunner.h | 8 | ||||
-rw-r--r-- | src/doxygen.cpp | 1 | ||||
-rw-r--r-- | src/index.cpp | 7 | ||||
-rw-r--r-- | src/util.cpp | 6 |
18 files changed, 406 insertions, 405 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7233052..217f391 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -181,16 +181,17 @@ add_library(_doxygen STATIC docparser.cpp docsets.cpp dot.cpp - dotcallgraph.cpp - dotclassgraph.cpp - dotdirdeps.cpp - dotfilepatcher.cpp + dotcallgraph.cpp + dotlegendgraph.cpp + dotclassgraph.cpp + dotdirdeps.cpp + dotfilepatcher.cpp dotgfxhierarchytable.cpp dotgraph.cpp - dotgroupcollaboration.cpp - dotincldepgraph.cpp + dotgroupcollaboration.cpp + dotincldepgraph.cpp dotnode.cpp - dotrunner.cpp + dotrunner.cpp doxygen.cpp eclipsehelp.cpp emoji.cpp diff --git a/src/configimpl.l b/src/configimpl.l index 2d91e12..e52a757 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -30,6 +30,7 @@ #include <qregexp.h> #include <qstack.h> #include <qglobal.h> +#include <qthread.h> #include "configimpl.h" #include "version.h" @@ -1531,6 +1532,7 @@ void Config::checkAndCorrect() // dotImageFormat = "png"; //} + // correct DOT_FONTNAME if needed QCString &dotFontName=Config_getString(DOT_FONTNAME); if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf") { @@ -1538,7 +1540,32 @@ void Config::checkAndCorrect() "You may want to clear or change DOT_FONTNAME.\n" "Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n"); } + else if (dotFontName.isEmpty()) + { + dotFontName = "Helvetica"; + } + // clip dotFontSize against the maximum bounds + int &dotFontSize = Config_getInt(DOT_FONTSIZE); + if (dotFontSize<4) + { + dotFontSize=4; + } + else if (dotFontSize>24) + { + dotFontSize=24; + } + + // clip number of threads + int &dotNumThreads = Config_getInt(DOT_NUM_THREADS); + if (dotNumThreads>32) + { + dotNumThreads=32; + } + else if (dotNumThreads<=0) + { + dotNumThreads=QMAX(2,QThread::idealThreadCount()+1); + } // check dot path QCString &dotPath = Config_getString(DOT_PATH); diff --git a/src/dot.cpp b/src/dot.cpp index 5cdf92c..5ad3916 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -16,12 +16,6 @@ #include <stdlib.h> #include <qdir.h> -#include <qfile.h> -#include <qqueue.h> -#include <qthread.h> -#include <qmutex.h> -#include <qwaitcondition.h> -#include <qregexp.h> #include "config.h" #include "dot.h" @@ -37,34 +31,8 @@ #define MAP_CMD "cmapx" -static int DOT_NUM_THREADS; // will be initialized in initDot - //-------------------------------------------------------------------- -void initDot() -{ - DotGraph::DOT_FONTNAME = Config_getString(DOT_FONTNAME); - if (DotGraph::DOT_FONTNAME.isEmpty()) - { - DotGraph::DOT_FONTNAME="Helvetica"; - } - - DotGraph::DOT_FONTSIZE = Config_getInt(DOT_FONTSIZE); - if (DotGraph::DOT_FONTSIZE<4) DotGraph::DOT_FONTSIZE=4; - - DOT_NUM_THREADS = Config_getInt(DOT_NUM_THREADS); - if (DOT_NUM_THREADS > 32) DOT_NUM_THREADS = 32; - if (DOT_NUM_THREADS <= 0) DOT_NUM_THREADS = QMAX(2,QThread::idealThreadCount()+1); - - // these are copied to be sure to be thread save - DotRunner::DOT_CLEANUP = Config_getBool(DOT_CLEANUP); - DotRunner::DOT_MULTI_TARGETS = Config_getBool(DOT_MULTI_TARGETS); - DotRunner::DOT_EXE.init(Config_getString(DOT_PATH) + "dot"); - - DotGraph::IMG_EXT = getDotImageExtension(); -} - - static QCString g_dotFontPath; static void setDotFontPath(const char *path) @@ -102,95 +70,6 @@ static void unsetDotFontPath() g_dotFontPath=""; } -// extract size from a dot generated SVG file -static bool readSVGSize(const QCString &fileName,int *width,int *height) -{ - bool found=FALSE; - QFile f(fileName); - if (!f.open(IO_ReadOnly)) - { - return FALSE; - } - const int maxLineLen=4096; - char buf[maxLineLen]; - while (!f.atEnd() && !found) - { - int numBytes = f.readLine(buf,maxLineLen-1); // read line - if (numBytes>0) - { - buf[numBytes]='\0'; - if (qstrncmp(buf,"<!--zoomable ",13)==0) - { - *width=-1; - *height=-1; - sscanf(buf,"<!--zoomable %d",height); - //printf("Found zoomable for %s!\n",fileName.data()); - found=TRUE; - } - else if (sscanf(buf,"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2) - { - //printf("Found fixed size %dx%d for %s!\n",*width,*height,fileName.data()); - found=TRUE; - } - } - else // read error! - { - //printf("Read error %d!\n",numBytes); - return FALSE; - } - } - return TRUE; -} - -static void writeSVGNotSupported(FTextStream &out) -{ - out << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; -} - -// check if a reference to a SVG figure can be written and does so if possible. -// return FALSE if not possible (for instance because the SVG file is not yet generated). -bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName) -{ - int width=600,height=600; - if (!readSVGSize(absImgName,&width,&height)) - { - return FALSE; - } - if (width==-1) - { - if (height<=60) - height=300; - else - height+=300; // add some extra space for zooming - if (height>600) height=600; // clip to maximum height of 600 pixels - out << "<div class=\"zoom\">"; - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" - << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">"; - } - else - { - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" - << relPath << baseName << ".svg\" width=\"" - << ((width*96+48)/72) << "\" height=\"" - << ((height*96+48)/72) << "\">"; - } - writeSVGNotSupported(out); - //out << "</object>"; - //out << "</embed>"; - out << "</iframe>"; - if (width==-1) - { - out << "</div>"; - } - - return TRUE; -} - //-------------------------------------------------------------------- DotManager *DotManager::m_theInstance = 0; @@ -204,15 +83,16 @@ DotManager *DotManager::instance() return m_theInstance; } -DotManager::DotManager() : m_dotMaps(1009) +DotManager::DotManager() : m_runners(1009), m_filePatchers(1009) { m_runners.setAutoDelete(TRUE); - m_dotMaps.setAutoDelete(TRUE); + m_filePatchers.setAutoDelete(TRUE); m_queue = new DotRunnerQueue; int i; - if (DOT_NUM_THREADS!=1) + int dotNumThreads = Config_getInt(DOT_NUM_THREADS); + if (dotNumThreads!=1) { - for (i=0;i<DOT_NUM_THREADS;i++) + for (i=0;i<dotNumThreads;i++) { DotWorkerThread *thread = new DotWorkerThread(m_queue); thread->start(); @@ -253,62 +133,22 @@ DotRunner* DotManager::createRunner(const QCString& absDotName, const QCString& return run; } - -int DotManager::addMap(const QCString &file,const QCString &mapFile, - const QCString &relPath,bool urlOnly,const QCString &context, - const QCString &label) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addMap(mapFile,relPath,urlOnly,context,label); -} - -int DotManager::addFigure(const QCString &file,const QCString &baseName, - const QCString &figureName,bool heightCheck) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addFigure(baseName,figureName,heightCheck); -} - -int DotManager::addSVGConversion(const QCString &file,const QCString &relPath, - bool urlOnly,const QCString &context,bool zoomable, - int graphId) +DotFilePatcher *DotManager::createFilePatcher(const QCString &fileName) { - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) + DotFilePatcher *patcher = m_filePatchers.find(fileName); + if (patcher==0) { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); + patcher = new DotFilePatcher(fileName); + m_filePatchers.append(fileName,patcher); } - return map->addSVGConversion(relPath,urlOnly,context,zoomable,graphId); + return patcher; } -int DotManager::addSVGObject(const QCString &file,const QCString &baseName, - const QCString &absImgName,const QCString &relPath) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addSVGObject(baseName,absImgName,relPath); -} - -bool DotManager::run() +bool DotManager::run() const { uint numDotRuns = m_runners.count(); - uint numDotMaps = m_dotMaps.count(); - if (numDotRuns+numDotMaps>1) + uint numFilePatchers = m_filePatchers.count(); + if (numDotRuns+numFilePatchers>1) { if (m_workers.count()==0) { @@ -316,7 +156,7 @@ bool DotManager::run() } else { - msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numDotMaps,m_workers.count())); + msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numFilePatchers,m_workers.count())); } } int i=1; @@ -397,27 +237,27 @@ bool DotManager::run() // patch the output file and insert the maps and figures i=1; - SDict<DotFilePatcher>::Iterator di(m_dotMaps); - DotFilePatcher *map; + SDict<DotFilePatcher>::Iterator di(m_filePatchers); + const DotFilePatcher *fp; // since patching the svg files may involve patching the header of the SVG // (for zoomable SVGs), and patching the .html files requires reading that // header after the SVG is patched, we first process the .svg files and // then the other files. - for (di.toFirst();(map=di.current());++di) + for (di.toFirst();(fp=di.current());++di) { - if (map->file().right(4)==".svg") + if (fp->isSVGFile()) { - msg("Patching output file %d/%d\n",i,numDotMaps); - if (!map->run()) return FALSE; + msg("Patching output file %d/%d\n",i,numFilePatchers); + if (!fp->run()) return FALSE; i++; } } - for (di.toFirst();(map=di.current());++di) + for (di.toFirst();(fp=di.current());++di) { - if (map->file().right(4)!=".svg") + if (!fp->isSVGFile()) { - msg("Patching output file %d/%d\n",i,numDotMaps); - if (!map->run()) return FALSE; + msg("Patching output file %d/%d\n",i,numFilePatchers); + if (!fp->run()) return FALSE; i++; } } @@ -426,63 +266,6 @@ bool DotManager::run() //-------------------------------------------------------------------- -class GraphLegendDotGraph : public DotGraph -{ - private: - virtual QCString getBaseName() const - { - return "graph_legend"; - } - - virtual void computeTheGraph() - { - FTextStream md5stream(&m_theGraph); - writeGraphHeader(md5stream,theTranslator->trLegendTitle()); - md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; - md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"grey75\"];\n"; - md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n"; - writeGraphFooter(md5stream); - } - - virtual QCString getMapLabel() const - { - return ""; - } - - friend void generateGraphLegend(const char* path); -}; - -void generateGraphLegend(const char *path) -{ - QDir d(path); - GraphLegendDotGraph dg; - FTextStream ts; - dg.writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); - - if (getDotImageExtension()=="svg") - { - DotManager::instance()->addSVGObject( - dg.absBaseName()+Config_getString(HTML_FILE_EXTENSION), - "graph_legend", - dg.absImgName(),QCString()); - } - -} - void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format) { @@ -560,10 +343,8 @@ void writeDotImageMapFromFile(FTextStream &t, if (imgExt=="svg") // vector graphics { - //writeSVGFigureLink(t,relPath,inFile,inFile+".svg"); - //DotFilePatcher patcher(inFile+".svg"); QCString svgName=outDir+"/"+baseName+".svg"; - writeSVGFigureLink(t,relPath,baseName,svgName); + DotFilePatcher::writeSVGFigureLink(t,relPath,baseName,svgName); DotFilePatcher patcher(svgName); patcher.addSVGConversion("",TRUE,context,TRUE,graphId); patcher.run(); @@ -575,7 +356,7 @@ void writeDotImageMapFromFile(FTextStream &t, t << "<img src=\"" << relPath << imgName << "\" alt=\"" << imgName << "\" border=\"0\" usemap=\"#" << mapName << "\"/>" << endl; - convertMapFile(tt, absOutFile, relPath ,TRUE, context); + DotFilePatcher::convertMapFile(tt, absOutFile, relPath ,TRUE, context); if (!result.isEmpty()) { t << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">"; @@ -18,66 +18,43 @@ #include <qlist.h> #include <qdict.h> -#include <qwaitcondition.h> -#include <qmutex.h> -#include <qqueue.h> -#include <qthread.h> +#include <qcstring.h> + #include "sortdict.h" -#include "qgstring.h" -#include "qdir.h" -#include "qcstring.h" -#include "dotgraph.h" -#include "dotfilepatcher.h" -#include "dotrunner.h" + +#include "dotgraph.h" // only for GraphOutputFormat class FTextStream; class DotRunner; class DotRunnerQueue; class DotWorkerThread; +class DotFilePatcher; -/** Singleton that manages dot relation actions */ +/** Singleton that manages parallel dot invocations and patching files for embedding image maps */ class DotManager { public: static DotManager *instance(); - DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); - int addMap(const QCString &file,const QCString &mapFile, - const QCString &relPath,bool urlOnly, - const QCString &context,const QCString &label); - int addFigure(const QCString &file,const QCString &baseName, - const QCString &figureName,bool heightCheck); - int addSVGConversion(const QCString &file,const QCString &relPath, - bool urlOnly,const QCString &context,bool zoomable,int graphId); - int addSVGObject(const QCString &file,const QCString &baseName, - const QCString &figureNAme,const QCString &relPath); - bool run(); + DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); + DotFilePatcher *createFilePatcher(const QCString &fileName); + bool run() const; private: DotManager(); virtual ~DotManager(); QDict<DotRunner> m_runners; - SDict<DotFilePatcher> m_dotMaps; + SDict<DotFilePatcher> m_filePatchers; static DotManager *m_theInstance; DotRunnerQueue *m_queue; QList<DotWorkerThread> m_workers; }; -void initDot(); - -/** Generated a graphs legend page */ -void generateGraphLegend(const char *path); - void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format); void writeDotImageMapFromFile(FTextStream &t, const QCString& inFile, const QCString& outDir, const QCString& relPath,const QCString& baseName, const QCString& context,int graphId=-1); -bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName); -bool convertMapFile(FTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE, - const QCString &context=QCString()); #endif diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp index 85906d1..98c7ca7 100644 --- a/src/dotdirdeps.cpp +++ b/src/dotdirdeps.cpp @@ -22,14 +22,16 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph \"" << dd->displayName() << "\" {\n"; if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=transparent;\n"; } t << " compound=true\n"; - t << " node [ fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", fontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; - t << " edge [ labelfontsize=\"" << DotGraph::DOT_FONTSIZE << "\", labelfontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; + t << " node [ fontsize=\"" << fontSize << "\", fontname=\"" << fontName << "\"];\n"; + t << " edge [ labelfontsize=\"" << fontSize << "\", labelfontname=\"" << fontName << "\"];\n"; QDict<DirDef> dirsInGraph(257); @@ -39,7 +41,7 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" << dd->parent()->shortName() - << "\" fontname=\"" << DotGraph::DOT_FONTNAME << "\", fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", URL=\""; + << "\" fontname=\"" << fontName << "\", fontsize=\"" << fontSize << "\", URL=\""; t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; t << "\"]\n"; } diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 91b7c78..92a5618 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -14,6 +14,7 @@ */ #include "dotfilepatcher.h" +#include "dotrunner.h" #include "qstring.h" #include "config.h" @@ -209,7 +210,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, * map file was found * \returns TRUE if successful. */ -bool convertMapFile(FTextStream &t,const char *mapName, +bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName, const QCString relPath, bool urlOnly, const QCString &context) { @@ -255,9 +256,9 @@ DotFilePatcher::DotFilePatcher(const char *patchFile) m_maps.setAutoDelete(TRUE); } -QCString DotFilePatcher::file() const +bool DotFilePatcher::isSVGFile() const { - return m_patchFile; + return m_patchFile.right(4)==".svg"; } int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, @@ -320,7 +321,7 @@ int DotFilePatcher::addSVGObject(const QCString &baseName, return id; } -bool DotFilePatcher::run() +bool DotFilePatcher::run() const { //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); bool interactiveSVG_local = Config_getBool(INTERACTIVE_SVG); @@ -479,7 +480,7 @@ bool DotFilePatcher::run() Map *map = m_maps.at(mapId); //printf("patching FIG %d in file %s with contents of %s\n", // mapId,m_patchFile.data(),map->mapFile.data()); - if (!DotGraph::writeVecGfxFigure(t,map->label,map->mapFile)) + if (!writeVecGfxFigure(t,map->label,map->mapFile)) { err("problem writing FIG %d figure!\n",mapId); return FALSE; @@ -537,3 +538,144 @@ bool DotFilePatcher::run() QDir::current().remove(tmpName); return TRUE; } + +//--------------------------------------------------------------------------------------------- + + +// extract size from a dot generated SVG file +static bool readSVGSize(const QCString &fileName,int *width,int *height) +{ + bool found=FALSE; + QFile f(fileName); + if (!f.open(IO_ReadOnly)) + { + return FALSE; + } + const int maxLineLen=4096; + char buf[maxLineLen]; + while (!f.atEnd() && !found) + { + int numBytes = f.readLine(buf,maxLineLen-1); // read line + if (numBytes>0) + { + buf[numBytes]='\0'; + if (qstrncmp(buf,"<!--zoomable ",13)==0) + { + *width=-1; + *height=-1; + sscanf(buf,"<!--zoomable %d",height); + //printf("Found zoomable for %s!\n",fileName.data()); + found=TRUE; + } + else if (sscanf(buf,"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2) + { + //printf("Found fixed size %dx%d for %s!\n",*width,*height,fileName.data()); + found=TRUE; + } + } + else // read error! + { + //printf("Read error %d!\n",numBytes); + return FALSE; + } + } + return TRUE; +} + +static void writeSVGNotSupported(FTextStream &out) +{ + out << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; +} + +/// Check if a reference to a SVG figure can be written and do so if possible. +/// Returns FALSE if not possible (for instance because the SVG file is not yet generated). +bool DotFilePatcher::writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName) +{ + int width=600,height=600; + if (!readSVGSize(absImgName,&width,&height)) + { + return FALSE; + } + if (width==-1) + { + if (height<=60) height=300; else height+=300; // add some extra space for zooming + if (height>600) height=600; // clip to maximum height of 600 pixels + out << "<div class=\"zoom\">"; + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">"; + } + else + { + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + << relPath << baseName << ".svg\" width=\"" + << ((width*96+48)/72) << "\" height=\"" + << ((height*96+48)/72) << "\">"; + } + writeSVGNotSupported(out); + //out << "</object>"; + //out << "</embed>"; + out << "</iframe>"; + if (width==-1) + { + out << "</div>"; + } + + return TRUE; +} + +bool DotFilePatcher::writeVecGfxFigure(FTextStream &out,const QCString &baseName, + const QCString &figureName) +{ + int width=400,height=550; + if (Config_getBool(USE_PDFLATEX)) + { + if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + else + { + if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + //printf("Got PDF/EPS size %d,%d\n",width,height); + int maxWidth = 350; /* approx. page width in points, excl. margins */ + int maxHeight = 550; /* approx. page height in points, excl. margins */ + out << "\\nopagebreak\n" + "\\begin{figure}[H]\n" + "\\begin{center}\n" + "\\leavevmode\n"; + if (width>maxWidth || height>maxHeight) // figure too big for page + { + // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 + if (width*maxHeight>height*maxWidth) + { + out << "\\includegraphics[width=" << maxWidth << "pt]"; + } + else + { + out << "\\includegraphics[height=" << maxHeight << "pt]"; + } + } + else + { + out << "\\includegraphics[width=" << width << "pt]"; + } + + out << "{" << baseName << "}\n" + "\\end{center}\n" + "\\end{figure}\n"; + + //printf("writeVecGfxFigure()=1\n"); + return TRUE; +} diff --git a/src/dotfilepatcher.h b/src/dotfilepatcher.h index dd5c511..b68208d 100644 --- a/src/dotfilepatcher.h +++ b/src/dotfilepatcher.h @@ -19,21 +19,37 @@ #include "qcstring.h" #include "qlist.h" +class FTextStream; + /** Helper class to insert a set of map file into an output file */ class DotFilePatcher { public: DotFilePatcher(const char *patchFile); + int addMap(const QCString &mapFile,const QCString &relPath, bool urlOnly,const QCString &context,const QCString &label); + int addFigure(const QCString &baseName, const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly, const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &baseName, const QCString &figureName, const QCString &relPath); - bool run(); - QCString file() const; + bool run() const; + bool isSVGFile() const; + + static bool convertMapFile(FTextStream &t,const char *mapName, + const QCString relPath, bool urlOnly=FALSE, + const QCString &context=QCString()); + + static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName); + + static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, + const QCString& figureName); private: struct Map @@ -50,4 +66,5 @@ class DotFilePatcher QCString m_patchFile; }; + #endif diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index ca6bcca..df64d66 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -24,11 +24,12 @@ #include "dotrunner.h" #include "dotgraph.h" #include "dotnode.h" +#include "dotfilepatcher.h" #define MAP_CMD "cmapx" -QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot -int DotGraph::DOT_FONTSIZE; // will be initialized in initDot +//QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot +//int DotGraph::DOT_FONTSIZE; // will be initialized in initDot /*! Checks if a file "baseName".md5 exists. If so the contents * are compared with \a md5. If equal FALSE is returned. @@ -90,7 +91,7 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, { QGString tmpstr; FTextStream tmpout(&tmpstr); - convertMapFile(tmpout,mapFile,relPath,FALSE); + DotFilePatcher::convertMapFile(tmpout,mapFile,relPath,FALSE); if (!tmpstr.isEmpty()) { out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl; @@ -104,12 +105,10 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, //-------------------------------------------------------------------- -QCString DotGraph::IMG_EXT; - QCString DotGraph::imgName() const { return m_baseName + ((m_graphFormat == GOF_BITMAP) ? - ("." + IMG_EXT) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); + ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); } QCString DotGraph::writeGraph( @@ -209,6 +208,7 @@ bool DotGraph::prepareDotFile() void DotGraph::generateCode(FTextStream &t) { + QCString imgExt = getDotImageExtension(); if (m_graphFormat==GOF_BITMAP && m_textFormat==EOF_DocBook) { t << "<para>" << endl; @@ -216,7 +216,7 @@ void DotGraph::generateCode(FTextStream &t) t << " <mediaobject>" << endl; t << " <imageobject>" << endl; t << " <imagedata"; - t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << IMG_EXT << "\">"; + t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << imgExt << "\">"; t << "</imagedata>" << endl; t << " </imageobject>" << endl; t << " </mediaobject>" << endl; @@ -225,16 +225,20 @@ void DotGraph::generateCode(FTextStream &t) } else if (m_graphFormat==GOF_BITMAP && m_generateImageMap) // produce HTML to include the image { - if (IMG_EXT=="svg") // add link to SVG file without map file + if (imgExt=="svg") // add link to SVG file without map file { if (!m_noDivTag) t << "<div class=\"center\">"; - if (m_regenerate || !writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file + if (m_regenerate || !DotFilePatcher::writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file { if (m_regenerate) { - DotManager::instance()->addSVGConversion(absImgName(),m_relPath,FALSE,QCString(),m_zoomable,m_graphId); + DotManager::instance()-> + createFilePatcher(absImgName())-> + addSVGConversion(m_relPath,FALSE,QCString(),m_zoomable,m_graphId); } - int mapId = DotManager::instance()->addSVGObject(m_fileName,m_baseName,absImgName(),m_relPath); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addSVGObject(m_baseName,absImgName(),m_relPath); t << "<!-- SVG " << mapId << " -->" << endl; } if (!m_noDivTag) t << "</div>" << endl; @@ -247,16 +251,20 @@ void DotGraph::generateCode(FTextStream &t) t << endl; if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) { - int mapId = DotManager::instance()->addMap(m_fileName, absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addMap(absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); t << "<!-- MAP " << mapId << " -->" << endl; } } } else if (m_graphFormat==GOF_EPS) // produce tex to include the .eps image { - if (m_regenerate || !writeVecGfxFigure(t,m_baseName,absBaseName())) + if (m_regenerate || !DotFilePatcher::writeVecGfxFigure(t,m_baseName,absBaseName())) { - int figId = DotManager::instance()->addFigure(m_fileName,m_baseName,absBaseName(),FALSE /*TRUE*/); + int figId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addFigure(m_baseName,absBaseName(),FALSE /*TRUE*/); t << endl << "% FIG " << figId << endl; } } @@ -264,6 +272,8 @@ void DotGraph::generateCode(FTextStream &t) void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -284,12 +294,12 @@ void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\"," - "labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\",shape=record];\n"; + t << " edge [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\"," + "labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\",shape=record];\n"; } void DotGraph::writeGraphFooter(FTextStream &t) @@ -347,54 +357,3 @@ void DotGraph::computeGraph(DotNode *root, graphStr=buf.data(); } -bool DotGraph::writeVecGfxFigure(FTextStream &out,const QCString &baseName, - const QCString &figureName) -{ - int width=400,height=550; - if (Config_getBool(USE_PDFLATEX)) - { - if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - else - { - if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - //printf("Got PDF/EPS size %d,%d\n",width,height); - int maxWidth = 350; /* approx. page width in points, excl. margins */ - int maxHeight = 550; /* approx. page height in points, excl. margins */ - out << "\\nopagebreak\n" - "\\begin{figure}[H]\n" - "\\begin{center}\n" - "\\leavevmode\n"; - if (width>maxWidth || height>maxHeight) // figure too big for page - { - // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 - if (width*maxHeight>height*maxWidth) - { - out << "\\includegraphics[width=" << maxWidth << "pt]"; - } - else - { - out << "\\includegraphics[height=" << maxHeight << "pt]"; - } - } - else - { - out << "\\includegraphics[width=" << width << "pt]"; - } - - out << "{" << baseName << "}\n" - "\\end{center}\n" - "\\end{figure}\n"; - - //printf("writeVecGfxFigure()=1\n"); - return TRUE; -} diff --git a/src/dotgraph.h b/src/dotgraph.h index 27d6938..0eda3a8 100644 --- a/src/dotgraph.h +++ b/src/dotgraph.h @@ -34,11 +34,6 @@ class DotGraph DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {} virtual ~DotGraph() {} - static QCString DOT_FONTNAME; // will be initialized in initDot - static int DOT_FONTSIZE; // will be initialized in initDot - - static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, const QCString& figureName); - protected: /** returns node numbers. The Counter is reset by the constructor */ int getNextNodeNumber() { return ++m_curNodeNumber; } @@ -72,10 +67,6 @@ class DotGraph virtual void computeTheGraph() = 0; - static QCString IMG_EXT; - - friend void initDot(); - QCString absBaseName() const { return m_absPath + m_baseName; } QCString absDotName() const { return m_absPath + m_baseName + ".dot"; } QCString imgName() const; diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index be55ac0..f9a11e7 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -356,9 +356,10 @@ bool DotGroupCollaboration::isTrivial() const return m_usedNodes->count() <= 1; } -void DotGroupCollaboration::writeGraphHeader(FTextStream &t, - const QCString &title) const +void DotGroupCollaboration::writeGraphHeader(FTextStream &t,const QCString &title) const { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -374,8 +375,8 @@ void DotGroupCollaboration::writeGraphHeader(FTextStream &t, { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\",labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\",shape=box];\n"; + t << " edge [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\",labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\",shape=box];\n"; t << " rankdir=LR;\n"; } diff --git a/src/dotlegendgraph.cpp b/src/dotlegendgraph.cpp new file mode 100644 index 0000000..98e1f88 --- /dev/null +++ b/src/dotlegendgraph.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 by Dimitri van Heesch. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation under the terms of the GNU General Public License is hereby +* granted. No representations are made about the suitability of this software +* for any purpose. It is provided "as is" without express or implied warranty. +* See the GNU General Public License for more details. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotlegendgraph.h" +#include "util.h" +#include "config.h" +#include "doxygen.h" +#include "dot.h" +#include "language.h" +#include "dotfilepatcher.h" + +void DotLegendGraph::writeGraph(const char *path) +{ + FTextStream ts; + DotGraph::writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); + + if (getDotImageExtension()=="svg") + { + DotManager::instance()-> + createFilePatcher(absBaseName()+Config_getString(HTML_FILE_EXTENSION))-> + addSVGObject("graph_legend", absImgName(),QCString()); + } +} + +QCString DotLegendGraph::getBaseName() const +{ + return "graph_legend"; +} + +void DotLegendGraph::computeTheGraph() +{ + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,theTranslator->trLegendTitle()); + md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; + md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"red\"];\n"; + md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"grey75\"];\n"; + md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << fontSize << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << fontSize << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + writeGraphFooter(md5stream); +} + +QCString DotLegendGraph::getMapLabel() const +{ + return ""; +} + diff --git a/src/dotlegendgraph.h b/src/dotlegendgraph.h new file mode 100644 index 0000000..2d8eeec --- /dev/null +++ b/src/dotlegendgraph.h @@ -0,0 +1,35 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 by Dimitri van Heesch. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation under the terms of the GNU General Public License is hereby +* granted. No representations are made about the suitability of this software +* for any purpose. It is provided "as is" without express or implied warranty. +* See the GNU General Public License for more details. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTLEGENDGRAPH_H +#define DOTLEGENDGRAPH_H + +#include "dotgraph.h" + +/** Representation of a legend explaining the meaning of boxes, arrows, and colors */ +class DotLegendGraph : public DotGraph +{ + public: + void writeGraph(const char *path); + + private: + virtual QCString getBaseName() const; + virtual void computeTheGraph(); + virtual QCString getMapLabel() const; + +}; + +#endif + diff --git a/src/dotnode.cpp b/src/dotnode.cpp index ae06fb2..491bcb5 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -540,7 +540,7 @@ void DotNode::writeArrow(FTextStream &t, if (pointBack && !umlUseArrow) t << "dir=\"back\","; t << "color=\"" << eProps->edgeColorMap[ei->color()] - << "\",fontsize=\"" << DotGraph::DOT_FONTSIZE << "\","; + << "\",fontsize=\"" << Config_getInt(DOT_FONTSIZE) << "\","; t << "style=\"" << eProps->edgeStyleMap[ei->style()] << "\""; if (!ei->label().isEmpty()) { @@ -559,7 +559,7 @@ void DotNode::writeArrow(FTextStream &t, t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\""; } - if (format==GOF_BITMAP) t << ",fontname=\"" << DotGraph::DOT_FONTNAME << "\""; + if (format==GOF_BITMAP) t << ",fontname=\"" << Config_getString(DOT_FONTNAME) << "\""; t << "];" << endl; } diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index 3a621c7..c01a4e5 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -28,6 +28,7 @@ #define MAX_LATEX_GRAPH_INCH 150 #define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) +//----------------------------------------------------------------------------------------- // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. @@ -142,12 +143,11 @@ bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool return FALSE; } -bool DotRunner::DOT_CLEANUP; -bool DotRunner::DOT_MULTI_TARGETS; -DotConstString DotRunner::DOT_EXE; +//--------------------------------------------------------------------------------- DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash) - : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(DOT_CLEANUP) + : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(Config_getBool(DOT_CLEANUP)), + m_dotExe(Config_getString(DOT_PATH)+"dot") { m_jobs.setAutoDelete(TRUE); } @@ -183,7 +183,7 @@ bool DotRunner::run() DotJob *s; // create output - if (DOT_MULTI_TARGETS) + if (Config_getBool(DOT_MULTI_TARGETS)) { dotArgs=QCString("\"")+m_file.data()+"\""; for (li.toFirst();(s=li.current());++li) @@ -191,14 +191,14 @@ bool DotRunner::run() dotArgs+=' '; dotArgs+=s->args.data(); } - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } else { for (li.toFirst();(s=li.current());++li) { dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -214,7 +214,7 @@ bool DotRunner::run() { if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error; dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -245,7 +245,7 @@ bool DotRunner::run() return TRUE; error: err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", - exitCode,DOT_EXE.data(),dotArgs.data()); + exitCode,m_dotExe.data(),dotArgs.data()); return FALSE; } diff --git a/src/dotrunner.h b/src/dotrunner.h index 4128fe8..1b68c18 100644 --- a/src/dotrunner.h +++ b/src/dotrunner.h @@ -34,7 +34,6 @@ class DotConstString DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } const char *data() const { return m_str; } bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } - void init(const char *s) { set(s); } private: void set(char const* s) @@ -101,14 +100,9 @@ class DotRunner private: DotConstString m_file; DotConstString m_md5Hash; + DotConstString m_dotExe; bool m_cleanUp; QList<DotJob> m_jobs; - - static bool DOT_CLEANUP; - static bool DOT_MULTI_TARGETS; - static DotConstString DOT_EXE; - friend void initDot(); - }; /** Queue of dot jobs to run. */ diff --git a/src/doxygen.cpp b/src/doxygen.cpp index a6455fc..f8e54de 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -11680,7 +11680,6 @@ void generateOutput() } initSearchIndexer(); - initDot(); bool generateHtml = Config_getBool(GENERATE_HTML); bool generateLatex = Config_getBool(GENERATE_LATEX); diff --git a/src/index.cpp b/src/index.cpp index 0631ee4..f5faea4 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -41,6 +41,7 @@ #include "ftvhelp.h" #include "dot.h" #include "dotgfxhierarchytable.h" +#include "dotlegendgraph.h" #include "pagedef.h" #include "dirdef.h" #include "vhdldocgen.h" @@ -3919,7 +3920,9 @@ void writeGraphInfo(OutputList &ol) if (!Config_getBool(HAVE_DOT) || !Config_getBool(GENERATE_HTML)) return; ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - generateGraphLegend(Config_getString(HTML_OUTPUT)); + + DotLegendGraph gd; + gd.writeGraph(Config_getString(HTML_OUTPUT)); bool &stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS); bool oldStripCommentsState = stripCommentsStateRef; @@ -3944,7 +3947,7 @@ void writeGraphInfo(OutputList &ol) legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e); //printf("legendDocs=%s\n",legendDocs.data()); } - FileDef *fd = createFileDef("","graph_legend"); + FileDef *fd = createFileDef("","graph_legend.dox"); ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE); delete fd; diff --git a/src/util.cpp b/src/util.cpp index 8816de1..4dc7c71 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -9051,9 +9051,9 @@ bool mainPageHasTitle() QCString getDotImageExtension(void) { - QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); - imgExt = imgExt.replace( QRegExp(":.*"), "" ); - return imgExt; + QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); + int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format + return i==-1 ? imgExt : imgExt.left(i); } bool openOutputFile(const char *outFile,QFile &f) |