summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2019-09-10 20:19:09 (GMT)
committerDimitri van Heesch <doxygen@gmail.com>2019-09-10 20:19:09 (GMT)
commitcc4253926526efc87385de9640e64cd5cf062ada (patch)
tree3bddf87f17e99be18dfcd24d460b9e4f264964bc
parent81da20ff839843634ee6db5f517bfcb7ef87d4b9 (diff)
downloadDoxygen-cc4253926526efc87385de9640e64cd5cf062ada.zip
Doxygen-cc4253926526efc87385de9640e64cd5cf062ada.tar.gz
Doxygen-cc4253926526efc87385de9640e64cd5cf062ada.tar.bz2
Refactoring code for dot related source files
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/configimpl.l27
-rw-r--r--src/dot.cpp273
-rw-r--r--src/dot.h43
-rw-r--r--src/dotdirdeps.cpp8
-rw-r--r--src/dotfilepatcher.cpp152
-rw-r--r--src/dotfilepatcher.h21
-rw-r--r--src/dotgraph.cpp101
-rw-r--r--src/dotgraph.h9
-rw-r--r--src/dotgroupcollaboration.cpp11
-rw-r--r--src/dotlegendgraph.cpp72
-rw-r--r--src/dotlegendgraph.h35
-rw-r--r--src/dotnode.cpp4
-rw-r--r--src/dotrunner.cpp18
-rw-r--r--src/dotrunner.h8
-rw-r--r--src/doxygen.cpp1
-rw-r--r--src/index.cpp7
-rw-r--r--src/util.cpp6
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 << "\">";
diff --git a/src/dot.h b/src/dot.h
index 124a32b..12ee540 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -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)