diff options
Diffstat (limited to 'src/dot.cpp')
-rw-r--r-- | src/dot.cpp | 273 |
1 files changed, 27 insertions, 246 deletions
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 << "\">"; |