summaryrefslogtreecommitdiffstats
path: root/src/dot.cpp
diff options
context:
space:
mode:
authorDimitri van Heesch <dimitri@stack.nl>2010-06-03 09:24:48 (GMT)
committerDimitri van Heesch <dimitri@stack.nl>2010-06-03 09:24:48 (GMT)
commita1528245b280f1068daad8cd850ea345a3f8b568 (patch)
tree060dc6ccdb347682a1d4b73ab3098d95599532f2 /src/dot.cpp
parenta3b06c4fd310fdeda48a4730139cee09b5302072 (diff)
downloadDoxygen-a1528245b280f1068daad8cd850ea345a3f8b568.zip
Doxygen-a1528245b280f1068daad8cd850ea345a3f8b568.tar.gz
Doxygen-a1528245b280f1068daad8cd850ea345a3f8b568.tar.bz2
Release-1.6.3-20100603
Diffstat (limited to 'src/dot.cpp')
-rw-r--r--src/dot.cpp1220
1 files changed, 779 insertions, 441 deletions
diff --git a/src/dot.cpp b/src/dot.cpp
index 5d9b975..565aa68 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -40,6 +40,11 @@
#include <qfile.h>
#include "ftextstream.h"
#include <md5.h>
+#include <qqueue.h>
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
#define MAP_CMD "cmapx"
@@ -81,7 +86,7 @@ static const char *edgeStyleMap[] =
static QCString getDotFontName()
{
static QCString dotFontName = Config_getString("DOT_FONTNAME");
- if (dotFontName.isEmpty()) dotFontName="FreeSans";
+ if (dotFontName.isEmpty()) dotFontName="FreeSans.ttf";
return dotFontName;
}
@@ -151,7 +156,6 @@ static bool convertMapFile(FTextStream &t,const char *mapName,
{
QCString link = buf.mid(indexS+6,indexE-indexS-6);
QCString result;
- QCString *dest;
if (urlOnly) // for user defined dot graphs
{
if (link.left(5)=="\\ref ") // \ref url
@@ -159,15 +163,7 @@ static bool convertMapFile(FTextStream &t,const char *mapName,
result="href=\"";
// fake ref node to resolve the url
DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context );
- if (!df->ref().isEmpty())
- {
- if ((dest=Doxygen::tagDestinationDict[df->ref()]))
- result += *dest + "/";
- }
- else if (!relPath.isEmpty())
- {
- result += relPath;
- }
+ result+=externalRef(relPath,df->ref(),TRUE);
if (!df->file().isEmpty())
result += df->file().data() + Doxygen::htmlFileExtension;
if (!df->anchor().isEmpty())
@@ -189,19 +185,10 @@ static bool convertMapFile(FTextStream &t,const char *mapName,
QCString url = link.mid(marker+1);
if (!ref.isEmpty())
{
- result = "target=\"_blank\" doxygen=\"" + ref + ":";
- if ((dest=Doxygen::tagDestinationDict[ref])) result += *dest + "/";
- result += "\" ";
+ result = externalLinkTarget() + externalRef(relPath,ref,FALSE);
}
result+= "href=\"";
- if (!ref.isEmpty())
- {
- if ((dest=Doxygen::tagDestinationDict[ref])) result += *dest + "/";
- }
- else if (!relPath.isEmpty())
- {
- result += relPath;
- }
+ result+=externalRef(relPath,ref,TRUE);
result+= url + "\"";
}
else // should not happen, but handle properly anyway
@@ -298,30 +285,97 @@ static void unsetDotFontPath()
g_dotFontPath="";
}
-static bool readBoundingBoxEPS(const char *fileName,int *width,int *height)
+static bool readBoundingBox(const char *fileName,int *width,int *height,bool isEps)
{
- QCString bb("%%PageBoundingBox:");
+ QCString bb = isEps ? QCString("%%PageBoundingBox:") : QCString(" /MediaBox [ ");
QFile f(fileName);
- if (!f.open(IO_ReadOnly)) return FALSE;
+ if (!f.open(IO_ReadOnly|IO_Raw))
+ {
+ //printf("readBoundingBox: could not open %s\n",fileName);
+ return FALSE;
+ }
const int maxLineLen=1024;
char buf[maxLineLen];
while (!f.atEnd())
{
int numBytes = f.readLine(buf,maxLineLen-1); // read line
- buf[numBytes]='\0';
- if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundingBox string
+ if (numBytes>0)
{
- int x,y;
- if (sscanf(buf+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4)
+ buf[numBytes]='\0';
+ if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundingBox string
{
- return FALSE;
+ int x,y;
+ if (sscanf(buf+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4)
+ {
+ //printf("readBoundingBox sscanf fail\n");
+ return FALSE;
+ }
+ return TRUE;
}
- return TRUE;
+ }
+ else // read error!
+ {
+ //printf("Read error %d!\n",numBytes);
+ return FALSE;
}
}
+ //printf("readBoundingBox: bounding box not found\n");
return FALSE;
}
+static bool writeVecGfxFigure(FTextStream &out,const QCString &baseName,
+ const QCString &figureName)
+{
+ int width=420,height=600;
+ static bool usePdfLatex = Config_getBool("USE_PDFLATEX");
+ if (usePdfLatex)
+ {
+ if (!readBoundingBox(figureName+".pdf",&width,&height,FALSE))
+ {
+ //printf("writeVecGfxFigure()=0\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!readBoundingBox(figureName+".eps",&width,&height,TRUE))
+ {
+ //printf("writeVecGfxFigure()=0\n");
+ return FALSE;
+ }
+ }
+ //printf("Got PDF/EPS size %d,%d\n",width,height);
+ int maxWidth = 400; /* approx. page width in points, excl. margins */
+ int maxHeight = 600; /* 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;
+}
+
// since dot silently reproduces the input file when it does not
// support the PNG format, we need to check the result.
static void checkDotResult(const QCString &imgName)
@@ -355,6 +409,27 @@ static void checkDotResult(const QCString &imgName)
}
}
+static bool insertMapFile(FTextStream &out,const QCString &mapFile,
+ const QCString &relPath,const QCString &mapLabel)
+{
+ QFileInfo fi(mapFile);
+ if (fi.exists() && fi.size()>0) // reuse existing map file
+ {
+ QGString tmpstr;
+ FTextStream tmpout(&tmpstr);
+ convertMapFile(tmpout,mapFile,relPath);
+ if (!tmpstr.isEmpty())
+ {
+ out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl;
+ out << tmpstr;
+ out << "</map>" << endl;
+ }
+ return TRUE;
+ }
+ return FALSE; // no map file yet, need to generate it
+}
+
+
/*! Checks if a file "baseName".md5 exists. If so the contents
* are compared with \a md5. If equal FALSE is returned. If the .md5
* file does not exist or its contents are not equal to \a md5,
@@ -386,6 +461,24 @@ static bool checkAndUpdateMd5Signature(const QCString &baseName,const QCString &
return TRUE;
}
+static bool checkDeliverables(const QCString &file1,
+ const QCString &file2=QCString())
+{
+ bool file1Ok = TRUE;
+ bool file2Ok = TRUE;
+ if (!file1.isEmpty())
+ {
+ QFileInfo fi(file1);
+ file1Ok = (fi.exists() && fi.size()>0);
+ }
+ if (!file2.isEmpty())
+ {
+ QFileInfo fi(file2);
+ file2Ok = (fi.exists() && fi.size()>0);
+ }
+ return file1Ok && file2Ok;
+}
+
//--------------------------------------------------------------------
class DotNodeList : public QList<DotNode>
@@ -401,8 +494,13 @@ class DotNodeList : public QList<DotNode>
//--------------------------------------------------------------------
-DotRunner::DotRunner(const char *file) : m_file(file)
+DotRunner::DotRunner(const QCString &file,const QCString &path,
+ bool checkResult,const QCString &imageName)
+ : m_file(file), m_path(path),
+ m_checkResult(checkResult), m_imageName(imageName)
{
+ static bool dotCleanUp = Config_getBool("DOT_CLEANUP");
+ m_cleanUp = dotCleanUp;
m_jobs.setAutoDelete(TRUE);
}
@@ -421,11 +519,12 @@ void DotRunner::addPostProcessing(const char *cmd,const char *args)
bool DotRunner::run()
{
int exitCode=0;
- static QCString dotExe = Config_getString("DOT_PATH")+"dot";
+ static QCString dotExe = Config_getString("DOT_PATH")+"dot";
+ static bool multiTargets = Config_getBool("DOT_MULTI_TARGETS");
QCString dotArgs;
QListIterator<QCString> li(m_jobs);
QCString *s;
- if (Config_getBool("DOT_MULTI_TARGETS"))
+ if (multiTargets)
{
dotArgs="\""+m_file+"\"";
for (li.toFirst();(s=li.current());++li)
@@ -454,6 +553,12 @@ bool DotRunner::run()
err("Error: Problems running '%s' as a post-processing step for dot output\n",m_postCmd.data());
return FALSE;
}
+ if (m_checkResult) checkDotResult(m_imageName);
+ if (m_cleanUp)
+ {
+ //printf("removing dot file %s\n",m_file.data());
+ QDir(m_path).remove(m_file);
+ }
return TRUE;
error:
err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n",
@@ -463,6 +568,311 @@ error:
//--------------------------------------------------------------------
+DotMapConverter::DotMapConverter(const char *patchFile)
+ : m_patchFile(patchFile)
+{
+ m_maps.setAutoDelete(TRUE);
+}
+
+int DotMapConverter::addMap(const QCString &mapFile,const QCString &relPath,
+ bool urlOnly,const QCString &context,const QCString &label)
+{
+ int id = m_maps.count();
+ Map *map = new Map;
+ map->mapFile = mapFile;
+ map->relPath = relPath;
+ map->urlOnly = urlOnly;
+ map->context = context;
+ map->label = label;
+ m_maps.append(map);
+ return id;
+}
+
+int DotMapConverter::addFigure(const QCString &baseName,
+ const QCString &figureName,bool heightCheck)
+{
+ int id = m_maps.count();
+ Map *map = new Map;
+ map->mapFile = figureName;
+ map->urlOnly = heightCheck;
+ map->label = baseName;
+ m_maps.append(map);
+ return id;
+}
+
+bool DotMapConverter::run()
+{
+ //printf("DotMapConverter::run(): %s\n",m_patchFile.data());
+ QCString tmpName = m_patchFile+".tmp";
+ if (!QDir::current().rename(m_patchFile,tmpName))
+ {
+ err("Failed to rename file %s to %s!\n",m_patchFile.data(),tmpName.data());
+ return FALSE;
+ }
+ QFile fi(tmpName);
+ QFile fo(m_patchFile);
+ if (!fi.open(IO_ReadOnly))
+ {
+ err("Error opening file %s for patching!\n",tmpName.data());
+ QDir::current().rename(tmpName,m_patchFile);
+ return FALSE;
+ }
+ if (!fo.open(IO_WriteOnly))
+ {
+ err("Error opening file %s for patching!\n",m_patchFile.data());
+ QDir::current().rename(tmpName,m_patchFile);
+ return FALSE;
+ }
+ FTextStream t(&fo);
+ const int maxLineLen=100*1024;
+ while (!fi.atEnd()) // foreach line
+ {
+ QCString line(maxLineLen);
+ int numBytes = fi.readLine(line.data(),maxLineLen);
+ int i;
+ ASSERT(numBytes<maxLineLen);
+ if ((i=line.find("<!-- MAP"))!=-1)
+ {
+ int mapId=-1;
+ int n = sscanf(line,"<!-- MAP %d",&mapId);
+ if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
+ {
+ Map *map = m_maps.at(mapId);
+ //printf("patching MAP %d in file %s with contents of %s\n",
+ // mapId,m_patchFile.data(),map->mapFile.data());
+ t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl;
+ convertMapFile(t,map->mapFile,map->relPath,map->urlOnly,map->context);
+ t << "</map>" << endl;
+ }
+ else // error invalid map id!
+ {
+ err("Found invalid MAP id in file %s!\n",mapId,m_patchFile.data());
+ t << line;
+ }
+ }
+ else if ((i=line.find("% FIG"))!=-1)
+ {
+ int mapId=-1;
+ int n = sscanf(line.data()+i+2,"FIG %d",&mapId);
+ //printf("line='%s' n=%d\n",line.data()+i,n);
+ if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
+ {
+ 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());
+ writeVecGfxFigure(t,map->label,map->mapFile);
+ }
+ else // error invalid map id!
+ {
+ err("Found invalid bounding FIG id in file %s!\n",mapId,m_patchFile.data());
+ t << line;
+ }
+ }
+ else
+ {
+ t << line;
+ }
+ }
+ fi.close();
+ QDir::current().remove(tmpName);
+ return TRUE;
+}
+
+//--------------------------------------------------------------------
+
+void DotRunnerQueue::enqueue(DotRunner *runner)
+{
+ QMutexLocker locker(&m_mutex);
+ m_queue.enqueue(runner);
+ m_bufferNotEmpty.wakeAll();
+}
+
+DotRunner *DotRunnerQueue::dequeue()
+{
+ QMutexLocker locker(&m_mutex);
+ while (m_queue.isEmpty())
+ {
+ // wait until something is added to the queue
+ m_bufferNotEmpty.wait(&m_mutex);
+ }
+ DotRunner *result = m_queue.dequeue();
+ return result;
+}
+
+uint DotRunnerQueue::count() const
+{
+ QMutexLocker locker(&m_mutex);
+ return m_queue.count();
+}
+
+//--------------------------------------------------------------------
+
+DotWorkerThread::DotWorkerThread(int id,DotRunnerQueue *queue)
+ : m_id(id), m_queue(queue)
+{
+}
+
+void DotWorkerThread::run()
+{
+ DotRunner *runner;
+ while ((runner=m_queue->dequeue()))
+ {
+ runner->run();
+ }
+}
+
+//--------------------------------------------------------------------
+
+DotManager *DotManager::m_theInstance = 0;
+
+DotManager *DotManager::instance()
+{
+ if (!m_theInstance)
+ {
+ m_theInstance = new DotManager;
+ }
+ return m_theInstance;
+}
+
+DotManager::DotManager() : m_dotMaps(1007)
+{
+ m_dotRuns.setAutoDelete(TRUE);
+ m_dotMaps.setAutoDelete(TRUE);
+ m_queue = new DotRunnerQueue;
+ int i;
+ int numThreads = QMIN(32,Config_getInt("DOT_NUM_THREADS"));
+ if (numThreads==0) numThreads = QMAX(1,QThread::idealThreadCount()+1);
+ for (i=0;i<numThreads;i++)
+ {
+ DotWorkerThread *thread = new DotWorkerThread(i,m_queue);
+ thread->start();
+ if (thread->isRunning())
+ {
+ m_workers.append(thread);
+ }
+ else // no more threads available!
+ {
+ delete thread;
+ }
+ }
+ ASSERT(m_workers.count()>0);
+}
+
+DotManager::~DotManager()
+{
+ delete m_queue;
+}
+
+void DotManager::addRun(DotRunner *run)
+{
+ m_dotRuns.append(run);
+}
+
+int DotManager::addMap(const QCString &file,const QCString &mapFile,
+ const QCString &relPath,bool urlOnly,const QCString &context,
+ const QCString &label)
+{
+ DotMapConverter *map = m_dotMaps.find(file);
+ if (map==0)
+ {
+ map = new DotMapConverter(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)
+{
+ DotMapConverter *map = m_dotMaps.find(file);
+ if (map==0)
+ {
+ map = new DotMapConverter(file);
+ m_dotMaps.append(file,map);
+ }
+ return map->addFigure(baseName,figureName,heightCheck);
+}
+
+bool DotManager::run()
+{
+ msg("Generating dot graphs using %d parallel threads...\n",m_workers.count());
+ uint numDotRuns = m_dotRuns.count();
+ uint numDotMaps = m_dotMaps.count();
+ int i=1;
+ QListIterator<DotRunner> li(m_dotRuns);
+
+ bool setPath=FALSE;
+ if (Config_getBool("GENERATE_HTML"))
+ {
+ setDotFontPath(Config_getString("HTML_OUTPUT"));
+ setPath=TRUE;
+ }
+ else if (Config_getBool("GENERATE_LATEX"))
+ {
+ setDotFontPath(Config_getString("LATEX_OUTPUT"));
+ setPath=TRUE;
+ }
+ else if (Config_getBool("GENERATE_RTF"))
+ {
+ setDotFontPath(Config_getString("RTF_OUTPUT"));
+ setPath=TRUE;
+ }
+ portable_sysTimerStart();
+ // fill work queue with dot operations
+ DotRunner *dr;
+ for (li.toFirst();(dr=li.current());++li)
+ {
+ m_queue->enqueue(dr);
+ }
+ int prev=1;
+ // wait for the queue to become empty
+ while ((i=m_queue->count())>0)
+ {
+ i = numDotRuns - i;
+ while (i>=prev)
+ {
+ msg("Running dot for graph %d/%d\n",prev,numDotRuns);
+ prev++;
+ }
+ portable_sleep(100);
+ }
+ while ((int)numDotRuns>=prev)
+ {
+ msg("Running dot for graph %d/%d\n",prev,numDotRuns);
+ prev++;
+ }
+ // signal the workers we are done
+ for (i=0;i<(int)m_workers.count();i++)
+ {
+ m_queue->enqueue(0); // add terminator for each worker
+ }
+ // wait for the workers to finish
+ for (i=0;i<(int)m_workers.count();i++)
+ {
+ m_workers.at(i)->wait();
+ }
+ portable_sysTimerStop();
+ if (setPath)
+ {
+ unsetDotFontPath();
+ }
+
+ // patch the output file and insert the maps and figures
+ i=1;
+ SDict<DotMapConverter>::Iterator di(m_dotMaps);
+ DotMapConverter *map;
+ for (di.toFirst();(map=di.current());++di)
+ {
+ msg("Inserting map/figure %d/%d\n",i,numDotMaps);
+ if (!map->run()) return FALSE;
+ i++;
+ }
+ return TRUE;
+}
+
+
+//--------------------------------------------------------------------
+
/*! helper function that deletes all nodes in a connected graph, given
* one of the graph's nodes
@@ -1101,7 +1511,8 @@ const DotNode *DotNode::findDocNode() const
int DotGfxHierarchyTable::m_curNodeNumber;
-void DotGfxHierarchyTable::writeGraph(FTextStream &out,const char *path) const
+void DotGfxHierarchyTable::writeGraph(FTextStream &out,
+ const char *path,const char *fileName) const
{
//printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
//printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
@@ -1113,11 +1524,6 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out,const char *path) const
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
- //QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- //QDir::setCurrent(d.absPath());
- //QDir thisDir;
// put each connected subgraph of the hierarchy in a row of the HTML output
out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl;
@@ -1142,7 +1548,6 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out,const char *path) const
// compute md5 checksum of the graph were are about to generate
QGString theGraph;
FTextStream md5stream(&theGraph);
- //md5stream.setEncoding(md5stream.UnicodeUTF8);
writeGraphHeader(md5stream);
md5stream << " rankdir=LR;" << endl;
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
@@ -1165,44 +1570,42 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out,const char *path) const
QCString sigStr(33);
MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
MD5SigToString(md5_sig,sigStr.data(),33);
+ bool regenerate=FALSE;
if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
- !QFileInfo(absMapName).exists())
+ !checkDeliverables(absMapName))
{
+ regenerate=TRUE;
// image was new or has changed
QCString dotName=absBaseName+".dot";
QFile f(dotName);
if (!f.open(IO_WriteOnly)) return;
FTextStream t(&f);
- //t.setEncoding(t.UnicodeUTF8);
t << theGraph;
f.close();
resetReNumbering();
- DotRunner dotRun(dotName);
- dotRun.addJob(imgExt,absImgName);
- dotRun.addJob(MAP_CMD,absMapName);
- if (!dotRun.run())
- {
- out << "</table>" << endl;
- unsetDotFontPath();
- return;
- }
- checkDotResult(absImgName);
- if (Config_getBool("DOT_CLEANUP")) d.remove(dotName);
+ DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
+
}
Doxygen::indexList.addImageFile(imgName);
// write image and map in a table row
QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
out << "<tr><td><img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
- << mapLabel << "_map\"/>" << endl;
- out << "<map name=\"" << mapLabel << "_map\" id=\"" << mapLabel << "\">" << endl;
- convertMapFile(out,absMapName,"");
- out << "</map></td></tr>" << endl;
- //thisDir.remove(mapName);
+ << mapLabel << "\"/>" << endl;
+
+ if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel))
+ {
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(),
+ FALSE,QCString(),mapLabel);
+ out << "<!-- MAP " << mapId << " -->" << endl;
+ }
+
+ out << "</td></tr>" << endl;
}
out << "</table>" << endl;
-
- unsetDotFontPath();
}
void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper)
@@ -1779,7 +2182,6 @@ QCString computeMd5Signature(DotNode *root,
//printf("computeMd5Signature\n");
QGString buf;
FTextStream md5stream(&buf);
- //md5stream.setEncoding(md5stream.UnicodeUTF8);
writeGraphHeader(md5stream);
if (lrRank)
{
@@ -1855,7 +2257,6 @@ static bool updateDotGraph(DotNode *root,
if (f.open(IO_WriteOnly))
{
FTextStream t(&f);
- //t.setEncoding(t.UnicodeUTF8);
t << theGraph;
}
return TRUE;
@@ -1887,6 +2288,7 @@ QCString DotClassGraph::diskName() const
QCString DotClassGraph::writeGraph(FTextStream &out,
GraphOutputFormat format,
const char *path,
+ const char *fileName,
const char *relPath,
bool /*isTBRank*/,
bool generateImageMap) const
@@ -1897,7 +2299,7 @@ QCString DotClassGraph::writeGraph(FTextStream &out,
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
QCString baseName;
QCString mapName;
@@ -1917,10 +2319,16 @@ QCString DotClassGraph::writeGraph(FTextStream &out,
break;
}
baseName = convertNameToFile(diskName());
- QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString absBaseName = QCString(d.absPath())+"/"+baseName;
+ QCString absDotName = absBaseName+".dot";
+ QCString absMapName = absBaseName+".map";
+ QCString absPdfName = absBaseName+".pdf";
+ QCString absEpsName = absBaseName+".eps";
+ QCString absImgName = absBaseName+"."+imgExt;
+ bool regenerate = FALSE;
if (updateDotGraph(m_startNode,
m_graphType,
absBaseName,
@@ -1928,44 +2336,37 @@ QCString DotClassGraph::writeGraph(FTextStream &out,
m_lrRank,
m_graphType==DotNode::Inheritance,
TRUE
- )
- )
+ ) ||
+ !checkDeliverables(format==BITMAP ? absImgName :
+ usePDFLatex ? absPdfName : absEpsName,
+ format==BITMAP && generateImageMap ? absMapName : QCString())
+ )
{
+ regenerate=TRUE;
if (format==BITMAP) // run dot to create a bitmap image
{
QCString dotArgs(maxCmdLine);
- QCString absImgName = absBaseName+"."+imgExt;
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob(imgExt,absImgName);
- if (generateImageMap) dotRun.addJob(MAP_CMD,absBaseName+".map");
- if (!dotRun.run())
- {
- unsetDotFontPath();
- return baseName;
- }
- checkDotResult(absImgName);
+ DotRunner *dotRun = new DotRunner(absDotName,
+ d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
+
}
else if (format==EPS) // run dot to create a .eps image
{
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob("ps",absBaseName+".eps");
-
- if (Config_getBool("USE_PDFLATEX"))
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ if (usePDFLatex)
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absBaseName.data(),absBaseName.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ dotRun->addJob("pdf",absPdfName);
}
-
- if (!dotRun.run())
+ else
{
- unsetDotFontPath();
- return baseName;
+ dotRun->addJob("ps",absEpsName);
}
+ DotManager::instance()->addRun(dotRun);
}
- if (Config_getBool("DOT_CLEANUP")) d.remove(baseName+".dot");
}
Doxygen::indexList.addImageFile(baseName+"."+imgExt);
@@ -1989,49 +2390,21 @@ QCString DotClassGraph::writeGraph(FTextStream &out,
break;
}
out << "\"/></div>" << endl;
- QGString tmpstr;
- FTextStream tmpout(&tmpstr);
- convertMapFile(tmpout,absBaseName+".map",relPath);
- if (!tmpstr.isEmpty())
+ if (regenerate || !insertMapFile(out,absMapName,relPath,mapLabel))
{
- out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
+ FALSE,QCString(),mapLabel);
+ out << "<!-- MAP " << mapId << " -->" << endl;
}
}
else if (format==EPS) // produce tex to include the .eps image
{
- int width=420,height=600;
- if (!readBoundingBoxEPS(absBaseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- unsetDotFontPath();
- return baseName;
- }
- //printf("Got EPS size %d,%d\n",width,height);
- int maxWidth = 400; /* approx. page width in points, excl. margins */
- int maxHeight = 400; /* approx. page height in points, excl. margins */
- out << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n";
- if (width>maxWidth)
- {
- out << "\\includegraphics[width=" << maxWidth << "pt]";
- }
- else if (height>maxHeight)
- {
- out << "\\includegraphics[height=" << maxHeight << "pt]";
- }
- else
- {
- out << "\\includegraphics[width=" << width << "pt]";
- }
- out << "{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
+ if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
+ {
+ int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE /*TRUE*/);
+ out << endl << "% FIG " << figId << endl;
+ }
}
- unsetDotFontPath();
return baseName;
}
@@ -2225,6 +2598,7 @@ QCString DotInclDepGraph::diskName() const
QCString DotInclDepGraph::writeGraph(FTextStream &out,
GraphOutputFormat format,
const char *path,
+ const char *fileName,
const char *relPath,
bool generateImageMap
) const
@@ -2235,7 +2609,7 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out,
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
QCString baseName=m_diskName;
if (m_inverse) baseName+="_dep";
@@ -2243,11 +2617,16 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out,
baseName=convertNameToFile(baseName);
QCString mapName=escapeCharsInString(m_startNode->m_label,FALSE);
if (m_inverse) mapName+="dep";
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
QCString absBaseName = QCString(d.absPath())+"/"+baseName;
- QCString absMapName = QCString(d.absPath())+"/"+mapName;
+ QCString absDotName = absBaseName+".dot";
+ QCString absMapName = absBaseName+".map";
+ QCString absPdfName = absBaseName+".pdf";
+ QCString absEpsName = absBaseName+".eps";
+ QCString absImgName = absBaseName+"."+imgExt;
+ bool regenerate = FALSE;
if (updateDotGraph(m_startNode,
DotNode::Dependency,
absBaseName,
@@ -2255,42 +2634,36 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out,
FALSE, // lrRank
FALSE, // renderParents
m_inverse // backArrows
- )
- )
+ ) ||
+ !checkDeliverables(format==BITMAP ? absImgName :
+ usePDFLatex ? absPdfName : absEpsName,
+ format==BITMAP && generateImageMap ? absMapName : QCString())
+ )
{
+ regenerate=TRUE;
if (format==BITMAP)
{
// run dot to create a bitmap image
QCString dotArgs(maxCmdLine);
- QCString absImgName=absBaseName+"."+imgExt;
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob(imgExt,absImgName);
- if (generateImageMap) dotRun.addJob(MAP_CMD,absBaseName+".map");
- if (!dotRun.run())
- {
- unsetDotFontPath();
- return baseName;
- }
- checkDotResult(absImgName);
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
}
else if (format==EPS)
{
- // run dot to create a .eps image
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob("ps",absBaseName+".eps");
- if (Config_getBool("USE_PDFLATEX"))
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ if (usePDFLatex)
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absBaseName.data(),absBaseName.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ dotRun->addJob("pdf",absPdfName);
}
- if (!dotRun.run())
+ else
{
- unsetDotFontPath();
- return baseName;
+ dotRun->addJob("ps",absEpsName);
}
- }
+ DotManager::instance()->addRun(dotRun);
+
+ }
}
Doxygen::indexList.addImageFile(baseName+"."+imgExt);
@@ -2298,43 +2671,27 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out,
{
out << "<div class=\"center\"><img src=\"" << relPath << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"\"/>";
+ << mapName << "\" alt=\"\"/>";
out << "</div>" << endl;
- QGString tmpstr;
- FTextStream tmpout(&tmpstr);
- //tmpout.setEncoding(tmpout.UnicodeUTF8);
- convertMapFile(tmpout,absBaseName+".map",relPath);
- if (!tmpstr.isEmpty())
+
+ QCString absMapName = absBaseName+".map";
+ if (regenerate || !insertMapFile(out,absMapName,relPath,mapName))
{
- out << "<map name=\"" << mapName << "_map\" id=\"" << mapName << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
+ FALSE,QCString(),mapName);
+ out << "<!-- MAP " << mapId << " -->" << endl;
}
+
}
else if (format==EPS)
{
- int width,height;
- if (!readBoundingBoxEPS(absBaseName+".eps",&width,&height))
+ if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
{
- err("Error: Could not extract bounding box from .eps!\n");
- unsetDotFontPath();
- return baseName;
+ int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
+ out << endl << "% FIG " << figId << endl;
}
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
}
- if (Config_getBool("DOT_CLEANUP")) d.remove(baseName+".dot");
-
- unsetDotFontPath();
return baseName;
}
@@ -2518,7 +2875,8 @@ DotCallGraph::~DotCallGraph()
}
QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat format,
- const char *path,const char *relPath,bool generateImageMap) const
+ const char *path,const char *fileName,
+ const char *relPath,bool generateImageMap) const
{
QDir d(path);
// store the original directory
@@ -2526,14 +2884,20 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat format,
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
QCString baseName = m_diskName + (m_inverse ? "_icgraph" : "_cgraph");
- QCString mapName=baseName;
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString mapName = baseName;
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
QCString absBaseName = QCString(d.absPath())+"/"+baseName;
+ QCString absDotName = absBaseName+".dot";
+ QCString absMapName = absBaseName+".map";
+ QCString absPdfName = absBaseName+".pdf";
+ QCString absEpsName = absBaseName+".eps";
+ QCString absImgName = absBaseName+"."+imgExt;
+ bool regenerate=FALSE;
if (updateDotGraph(m_startNode,
DotNode::CallGraph,
absBaseName,
@@ -2541,41 +2905,37 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat format,
TRUE, // lrRank
FALSE, // renderParents
m_inverse // backArrows
- )
- )
+ ) ||
+ !checkDeliverables(format==BITMAP ? absImgName :
+ usePDFLatex ? absPdfName : absEpsName,
+ format==BITMAP && generateImageMap ? absMapName : QCString())
+ )
{
+ regenerate=TRUE;
if (format==BITMAP)
{
// run dot to create a bitmap image
QCString dotArgs(maxCmdLine);
- QCString absImgName=absBaseName+"."+imgExt;
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob(imgExt,absImgName);
- if (generateImageMap) dotRun.addJob(MAP_CMD,absBaseName+".map");
- if (!dotRun.run())
- {
- unsetDotFontPath();
- return baseName;
- }
- checkDotResult(absImgName);
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
+
}
else if (format==EPS)
{
// run dot to create a .eps image
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob("ps",absBaseName+".eps");
- if (Config_getBool("USE_PDFLATEX"))
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ if (usePDFLatex)
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absBaseName.data(),absBaseName.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ dotRun->addJob("pdf",absPdfName);
}
- if (!dotRun.run())
+ else
{
- unsetDotFontPath();
- return baseName;
+ dotRun->addJob("ps",absEpsName);
}
+ DotManager::instance()->addRun(dotRun);
+
}
}
Doxygen::indexList.addImageFile(baseName+"."+imgExt);
@@ -2584,44 +2944,27 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat format,
{
out << "<div class=\"center\"><img src=\"" << relPath << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"";
+ << mapName << "\" alt=\"";
out << "\"/>";
out << "</div>" << endl;
- QGString tmpstr;
- FTextStream tmpout(&tmpstr);
- //tmpout.setEncoding(tmpout.UnicodeUTF8);
- convertMapFile(tmpout,absBaseName+".map",relPath);
- if (!tmpstr.isEmpty())
+
+ if (regenerate || !insertMapFile(out,absMapName,relPath,mapName))
{
- out << "<map name=\"" << mapName << "_map\" id=\"" << mapName << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
+ FALSE,QCString(),mapName);
+ out << "<!-- MAP " << mapId << " -->" << endl;
}
+
}
else if (format==EPS)
{
- int width,height;
- if (!readBoundingBoxEPS(absBaseName+".eps",&width,&height))
+ if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
{
- err("Error: Could not extract bounding box from .eps!\n");
- unsetDotFontPath();
- return baseName;
+ int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
+ out << endl << "% FIG " << figId << endl;
}
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
}
- if (Config_getBool("DOT_CLEANUP")) d.remove(baseName+".dot");
-
- unsetDotFontPath();
return baseName;
}
@@ -2650,6 +2993,7 @@ DotDirDeps::~DotDirDeps()
QCString DotDirDeps::writeGraph(FTextStream &out,
GraphOutputFormat format,
const char *path,
+ const char *fileName,
const char *relPath,
bool generateImageMap) const
{
@@ -2659,58 +3003,66 @@ QCString DotDirDeps::writeGraph(FTextStream &out,
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
QCString baseName=m_dir->getOutputFileBase()+"_dep";
QCString mapName=escapeCharsInString(baseName,FALSE);
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
QCString absBaseName = QCString(d.absPath())+"/"+baseName;
-
- // TODO: create check, update md5 checksum
+ QCString absDotName = absBaseName+".dot";
+ QCString absMapName = absBaseName+".map";
+ QCString absPdfName = absBaseName+".pdf";
+ QCString absEpsName = absBaseName+".eps";
+ QCString absImgName = absBaseName+"."+imgExt;
+
+ // compute md5 checksum of the graph were are about to generate
+ QGString theGraph;
+ FTextStream md5stream(&theGraph);
+ m_dir->writeDepGraph(md5stream);
+ uchar md5_sig[16];
+ QCString sigStr(33);
+ MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
+ MD5SigToString(md5_sig,sigStr.data(),33);
+ bool regenerate=FALSE;
+ if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
+ !checkDeliverables(format==BITMAP ? absImgName :
+ usePDFLatex ? absPdfName : absEpsName,
+ format==BITMAP && generateImageMap ? absMapName : QCString())
+ )
{
- QFile f(absBaseName+".dot");
+ regenerate=TRUE;
+
+ QFile f(absDotName);
if (!f.open(IO_WriteOnly))
{
err("Cannot create file %s.dot for writing!\n",baseName.data());
}
FTextStream t(&f);
- //t.setEncoding(t.UnicodeUTF8);
- m_dir->writeDepGraph(t);
+ t << theGraph.data();
f.close();
if (format==BITMAP)
{
// run dot to create a bitmap image
QCString dotArgs(maxCmdLine);
- QCString absImgName=absBaseName+"."+imgExt;
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob(imgExt,absImgName);
- if (generateImageMap) dotRun.addJob(MAP_CMD,absBaseName+".map");
- if (!dotRun.run())
- {
- unsetDotFontPath();
- return baseName;
- }
- checkDotResult(absImgName);
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
}
else if (format==EPS)
{
- // run dot to create a .eps image
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob("ps",absBaseName+".eps");
- if (Config_getBool("USE_PDFLATEX"))
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ if (usePDFLatex)
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absBaseName.data(),absBaseName.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ dotRun->addJob("pdf",absPdfName);
}
- if (!dotRun.run())
+ else
{
- unsetDotFontPath();
- return baseName;
+ dotRun->addJob("ps",absEpsName);
}
+ DotManager::instance()->addRun(dotRun);
}
}
Doxygen::indexList.addImageFile(baseName+"."+imgExt);
@@ -2719,50 +3071,27 @@ QCString DotDirDeps::writeGraph(FTextStream &out,
{
out << "<div class=\"center\"><img src=\"" << relPath << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"";
+ << mapName << "\" alt=\"";
out << convertToXML(m_dir->displayName());
out << "\"/>";
out << "</div>" << endl;
- QGString tmpstr;
- FTextStream tmpout(&tmpstr);
- //tmpout.setEncoding(tmpout.UnicodeUTF8);
- convertMapFile(tmpout,absBaseName+".map",relPath,TRUE);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapName << "_map\" id=\"" << mapName << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- else
+
+ if (regenerate || !insertMapFile(out,absMapName,relPath,mapName))
{
- //printf("Map is empty!\n");
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
+ TRUE,QCString(),mapName);
+ out << "<!-- MAP " << mapId << " -->" << endl;
}
- //thisDir.remove(baseName+".map");
}
else if (format==EPS)
{
- int width,height;
- if (!readBoundingBoxEPS(absBaseName+".eps",&width,&height))
+ if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
{
- err("Error: Could not extract bounding box from .eps!\n");
- unsetDotFontPath();
- return baseName;
+ int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
+ out << endl << "% FIG " << figId << endl;
}
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
}
- if (Config_getBool("DOT_CLEANUP")) d.remove(baseName+".dot");
-
- unsetDotFontPath();
return baseName;
}
@@ -2775,58 +3104,65 @@ bool DotDirDeps::isTrivial() const
void generateGraphLegend(const char *path)
{
- QFile dotFile((QCString)path+"/graph_legend.dot");
- if (!dotFile.open(IO_WriteOnly))
- {
- err("Could not open file %s for writing\n",
- convertToQCString(dotFile.name()).data());
- return;
- }
- FTextStream dotText(&dotFile);
- writeGraphHeader(dotText);
- dotText << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n";
- dotText << " Node10 -> Node9 [dir=back,color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node11 -> Node10 [dir=back,color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node13 -> Node9 [dir=back,color=\"darkgreen\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node14 -> Node9 [dir=back,color=\"firebrick4\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node15 -> Node9 [dir=back,color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"grey75\"];\n";
- dotText << " Node16 -> Node9 [dir=back,color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node17 -> Node16 [dir=back,color=\"orange\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node18 -> Node9 [dir=back,color=\"darkorchid3\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << FONTNAME << "\"];\n";
- dotText << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n";
- writeGraphFooter(dotText);
- dotFile.close();
-
QDir d(path);
// store the original directory
if (!d.exists())
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
- // run dot to generate the a bitmap image from the graph
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString imgName = "graph_legend."+imgExt;
- QCString absImgName = QCString(d.absPath())+"/"+ imgName;
-
- DotRunner dotRun(d.absPath()+"/graph_legend.dot");
- dotRun.addJob(imgExt,absImgName);
- if (!dotRun.run())
+ QGString theGraph;
+ FTextStream md5stream(&theGraph);
+ writeGraphHeader(md5stream);
+ 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\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\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\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n";
+ writeGraphFooter(md5stream);
+ uchar md5_sig[16];
+ QCString sigStr(33);
+ MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
+ MD5SigToString(md5_sig,sigStr.data(),33);
+ QCString absBaseName = (QCString)path+"/graph_legend";
+ QCString absDotName = absBaseName+".dot";
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString imgName = "graph_legend."+imgExt;
+ QCString absImgName = absBaseName+"."+imgExt;
+ if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
+ !checkDeliverables(absImgName))
{
- unsetDotFontPath();
- return;
+ QFile dotFile(absDotName);
+ if (!dotFile.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",
+ convertToQCString(dotFile.name()).data());
+ return;
+ }
+
+ FTextStream dotText(&dotFile);
+ dotText << theGraph;
+ dotFile.close();
+
+ // run dot to generate the a bitmap image from the graph
+
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
+ dotRun->addJob(imgExt,absImgName);
+ DotManager::instance()->addRun(dotRun);
}
- checkDotResult(absImgName);
- Doxygen::indexList.addImageFile(imgName);
- unsetDotFontPath();
+
}
void writeDotGraphFromFile(const char *inFile,const char *outDir,
@@ -2837,37 +3173,37 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir,
{
err("Error: Output dir %s does not exist!\n",outDir); exit(1);
}
- setDotFontPath("");
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
QCString imgName = (QCString)outFile+"."+imgExt;
QCString absImgName = QCString(d.absPath())+"/"+imgName;
QCString absOutFile = QCString(d.absPath())+"/"+outFile;
- DotRunner dotRun(inFile);
+ DotRunner dotRun(inFile,d.absPath().data(),FALSE,absImgName);
if (format==BITMAP)
dotRun.addJob(imgExt,absImgName);
else // format==EPS
- dotRun.addJob("ps",absOutFile+".eps");
-
- if ( (format==EPS) && (Config_getBool("USE_PDFLATEX")) )
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absOutFile.data(),absOutFile.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ if (Config_getBool("USE_PDFLATEX"))
+ {
+ dotRun.addJob("pdf",absOutFile+".pdf");
+ }
+ else
+ {
+ dotRun.addJob("ps",absOutFile+".eps");
+ }
}
+ dotRun.preventCleanUp();
if (!dotRun.run())
{
- unsetDotFontPath();
return;
}
if (format==BITMAP) checkDotResult(absImgName);
+
Doxygen::indexList.addImageFile(imgName);
- unsetDotFontPath();
}
@@ -2875,40 +3211,38 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir,
* dotfiles to generate image maps.
* \param inFile just the basename part of the filename
* \param outDir output directory
+ * \param fileName file name in which the map will be embedded
* \param relPath relative path the to root of the output dir
* \param context the scope in which this graph is found (for resolving links)
* \returns a string which is the HTML image map (without the \<map\>\</map\>)
*/
QCString getDotImageMapFromFile(const QCString& inFile, const QCString& outDir,
- const QCString &relPath,const QCString &context)
+ const QCString &relPath, const QCString &context)
{
- QString outFile = inFile + ".map";
+ QCString outFile = inFile + ".map";
QDir d(outDir);
if (!d.exists())
{
err("Error: Output dir %s does not exist!\n",outDir.data()); exit(1);
}
- setDotFontPath(d.absPath());
- QCString absInFile = QCString(d.absPath())+"/"+inFile.data();
- QCString absOutFile = QCString(d.absPath())+"/"+outFile.data();
+ QCString absInFile = QCString(d.absPath())+"/"+inFile;
+ QCString absOutFile = QCString(d.absPath())+"/"+outFile;
- DotRunner dotRun(absInFile);
+ DotRunner dotRun(absInFile,d.absPath().data(),FALSE);
dotRun.addJob(MAP_CMD,absOutFile);
+ dotRun.preventCleanUp();
if (!dotRun.run())
{
- unsetDotFontPath();
return "";
}
QGString result;
FTextStream tmpout(&result);
- //tmpout.setEncoding(tmpout.UnicodeUTF8);
convertMapFile(tmpout, absOutFile, relPath ,TRUE, context);
d.remove(outFile);
- unsetDotFontPath();
return result.data();
}
// end MDG mods
@@ -3125,7 +3459,7 @@ void DotGroupCollaboration::addCollaborationMember(
QCString DotGroupCollaboration::writeGraph( FTextStream &t, GraphOutputFormat format,
- const char *path, const char *relPath,
+ const char *path, const char *fileName, const char *relPath,
bool writeImageMap) const
{
QDir d(path);
@@ -3134,113 +3468,117 @@ QCString DotGroupCollaboration::writeGraph( FTextStream &t, GraphOutputFormat fo
{
err("Error: Output dir %s does not exist!\n",path); exit(1);
}
- setDotFontPath(d.absPath());
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
- QCString baseName = m_diskName;
- QCString absBaseName = QCString(d.absPath())+"/"+baseName;
+ QGString theGraph;
+ FTextStream md5stream(&theGraph);
+ writeGraphHeader(md5stream);
- QFile dotfile(absBaseName+".dot");
- if (dotfile.open(IO_WriteOnly))
+ // clean write flags
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *pn;
+ for (dni.toFirst();(pn=dni.current());++dni)
{
- FTextStream tdot(&dotfile);
- //tdot.setEncoding(tdot.UnicodeUTF8);
- writeGraphHeader(tdot);
-
- // clean write flags
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *pn;
- for (dni.toFirst();(pn=dni.current());++dni)
- pn->clearWriteFlag();
-
- // write other nodes.
- for (dni.toFirst();(pn=dni.current());++dni)
- {
- pn->write(tdot,DotNode::Inheritance,format,TRUE,FALSE,FALSE,FALSE);
- }
-
- // write edges
- QListIterator<Edge> eli(m_edges);
- Edge* edge;
- for (eli.toFirst();(edge=eli.current());++eli)
- {
- edge->write( tdot );
- }
+ pn->clearWriteFlag();
+ }
- writeGraphFooter(tdot);
- dotfile.close();
+ // write other nodes.
+ for (dni.toFirst();(pn=dni.current());++dni)
+ {
+ pn->write(md5stream,DotNode::Inheritance,format,TRUE,FALSE,FALSE,FALSE);
}
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- if (format==BITMAP) // run dot to create a bitmap image
+ // write edges
+ QListIterator<Edge> eli(m_edges);
+ Edge* edge;
+ for (eli.toFirst();(edge=eli.current());++eli)
{
- QCString dotArgs(maxCmdLine);
- QCString imgName = baseName+"."+imgExt;
- QCString mapName=baseName+".map";
+ edge->write( md5stream );
+ }
- QCString absImgName = QCString(d.absPath())+"/"+imgName;
- QCString absMapName = QCString(d.absPath())+"/"+mapName;
+ writeGraphFooter(md5stream);
+ resetReNumbering();
+ uchar md5_sig[16];
+ QCString sigStr(33);
+ MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
+ MD5SigToString(md5_sig,sigStr.data(),33);
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString baseName = m_diskName;
+ QCString imgName = baseName+"."+imgExt;
+ QCString mapName = baseName+".map";
+ QCString absPath = d.absPath().data();
+ QCString absBaseName = absPath+"/"+baseName;
+ QCString absDotName = absBaseName+".dot";
+ QCString absImgName = absBaseName+"."+imgExt;
+ QCString absMapName = absBaseName+".map";
+ QCString absPdfName = absBaseName+".pdf";
+ QCString absEpsName = absBaseName+".eps";
+ bool regenerate=FALSE;
+ if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
+ !checkDeliverables(format==BITMAP ? absImgName :
+ usePDFLatex ? absPdfName : absEpsName,
+ format==BITMAP /*&& generateImageMap*/ ? absMapName : QCString())
+ )
+ {
+ regenerate=TRUE;
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob(imgExt,absImgName);
- if (writeImageMap) dotRun.addJob(MAP_CMD,absMapName);
- if (!dotRun.run())
+ QFile dotfile(absDotName);
+ if (dotfile.open(IO_WriteOnly))
{
- unsetDotFontPath();
- return baseName;
+ FTextStream tdot(&dotfile);
+ tdot << theGraph;
+ dotfile.close();
}
- if (writeImageMap)
+ if (format==BITMAP) // run dot to create a bitmap image
{
- QCString mapLabel = escapeCharsInString(baseName,FALSE);
- t << "<center><table><tr><td><img src=\"" << relPath << imgName
- << "\" border=\"0\" alt=\"\" usemap=\"#"
- << mapLabel << "_map\"/>" << endl;
- t << "<map name=\"" << mapLabel << "_map\" id=\"" << mapLabel << "\">" << endl;
- convertMapFile(t,absMapName,relPath);
- t << "</map></td></tr></table></center>" << endl;
+ QCString dotArgs(maxCmdLine);
+
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ dotRun->addJob(imgExt,absImgName);
+ if (writeImageMap) dotRun->addJob(MAP_CMD,absMapName);
+ DotManager::instance()->addRun(dotRun);
+
}
- }
- else if (format==EPS)
- {
- DotRunner dotRun(absBaseName+".dot");
- dotRun.addJob("ps",absBaseName+".eps");
- if (Config_getBool("USE_PDFLATEX"))
+ else if (format==EPS)
{
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- absBaseName.data(),absBaseName.data());
- dotRun.addPostProcessing("epstopdf",epstopdfArgs);
+ DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
+ if (usePDFLatex)
+ {
+ dotRun->addJob("pdf",absPdfName);
+ }
+ else
+ {
+ dotRun->addJob("ps",absEpsName);
+ }
+ DotManager::instance()->addRun(dotRun);
}
- if (!dotRun.run())
+ }
+ if (format==BITMAP && writeImageMap)
+ {
+ QCString mapLabel = escapeCharsInString(baseName,FALSE);
+ t << "<center><table><tr><td><img src=\"" << relPath << imgName
+ << "\" border=\"0\" alt=\"\" usemap=\"#"
+ << mapLabel << "\"/>" << endl;
+ if (regenerate || !insertMapFile(t,absMapName,relPath,mapLabel))
{
- unsetDotFontPath();
- return baseName;
+ int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
+ FALSE,QCString(),mapLabel);
+ t << "<!-- MAP " << mapId << " -->" << endl;
}
- int width,height;
- if (!readBoundingBoxEPS(absBaseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- unsetDotFontPath();
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
- t << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
+ t << "</td></tr></table></center>" << endl;
}
- if (Config_getBool("DOT_CLEANUP"))
+ else if (format==EPS)
{
- d.remove(baseName+".dot");
+ if (regenerate || !writeVecGfxFigure(t,baseName,absBaseName))
+ {
+ int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
+ t << endl << "% FIG " << figId << endl;
+ }
}
- unsetDotFontPath();
return baseName;
}