diff options
author | albert-github <albert.tests@gmail.com> | 2018-04-26 13:15:23 (GMT) |
---|---|---|
committer | albert-github <albert.tests@gmail.com> | 2018-04-26 13:15:23 (GMT) |
commit | 49079853fc4670c11b46e12eba7cb519608be8b0 (patch) | |
tree | d77a97380ebd683065035be53d4268fbe047e2d7 | |
parent | e75de3722b98115f27483aeacb3b2b1dbe7114a3 (diff) | |
download | Doxygen-49079853fc4670c11b46e12eba7cb519608be8b0.zip Doxygen-49079853fc4670c11b46e12eba7cb519608be8b0.tar.gz Doxygen-49079853fc4670c11b46e12eba7cb519608be8b0.tar.bz2 |
Large CALL / CALLER graphs cannot be processed in LaTeX
When generating CAL or CALLER graphs thy can become quite large (and unreadable) and it won't be possible to process them into a PDF due to a limitation of TeX.
When it is determined that the resulting image is to large a scale down is done to around 150" (still unreadable) but it can be processed, this scaling done is done by means of the `dot` program.
(Note: the scaling to 550 points for the output occurs on the original image in the TeX processing and Tex cannot read the image).
-rw-r--r-- | src/dot.cpp | 98 | ||||
-rw-r--r-- | src/dot.h | 28 |
2 files changed, 109 insertions, 17 deletions
diff --git a/src/dot.cpp b/src/dot.cpp index 80703b9..eeb8b8b 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -266,6 +266,7 @@ static void writeGraphHeader(FTextStream &t,const QCString &title=QCString()) { t << " // INTERACTIVE_SVG=YES\n"; } + t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size repacement if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=\"transparent\";" << endl; @@ -437,6 +438,55 @@ static void unsetDotFontPath() g_dotFontPath=""; } +static bool resetPDFSize(const int width,const int height, const char *base) +{ + QString tmpName = QString::fromUtf8(QCString(base)+".tmp"); + QString patchFile = QString::fromUtf8(QCString(base)+".dot"); + if (!QDir::current().rename(patchFile,tmpName)) + { + err("Failed to rename file %s to %s!\n",patchFile.data(),tmpName.data()); + return FALSE; + } + QFile fi(tmpName); + QFile fo(patchFile); + if (!fi.open(IO_ReadOnly)) + { + err("problem opening file %s for patching!\n",tmpName.data()); + QDir::current().rename(tmpName,patchFile); + return FALSE; + } + if (!fo.open(IO_WriteOnly)) + { + err("problem opening file %s for patching!\n",patchFile.data()); + QDir::current().rename(tmpName,patchFile); + fi.close(); + return FALSE; + } + FTextStream t(&fo); + const int maxLineLen=100*1024; + while (!fi.atEnd()) // foreach line + { + QCString line(maxLineLen); + int numBytes = fi.readLine(line.rawData(),maxLineLen); + if (numBytes<=0) + { + break; + } + line.resize(numBytes+1); + if (line.find("LATEX_PDF_SIZE") != -1) + { + double scale = (width > height ? width : height)/double(MAX_LATEX_GRAPH_INCH); + t << " size=\""<<width/scale << "," <<height/scale <<"\";\n"; + } + else + t << line; + } + fi.close(); + fo.close(); + // remove temporary file + QDir::current().remove(tmpName); + return TRUE; +} static bool readBoundingBox(const char *fileName,int *width,int *height,bool isEps) { QCString bb = isEps ? QCString("%%PageBoundingBox:") : QCString("/MediaBox ["); @@ -765,10 +815,10 @@ DotRunner::DotRunner(const QCString &file,const QCString &path, m_jobs.setAutoDelete(TRUE); } -void DotRunner::addJob(const char *format,const char *output) +void DotRunner::addJob(const char *format,const char *output, const char *base) { QCString args = QCString("-T")+format+" -o \""+output+"\""; - m_jobs.append(new DotConstString(args)); + m_jobs.append(new DotConstString(args, base)); } void DotRunner::addPostProcessing(const char *cmd,const char *args) @@ -780,6 +830,7 @@ void DotRunner::addPostProcessing(const char *cmd,const char *args) bool DotRunner::run() { int exitCode=0; + int width=0,height=0; QCString dotArgs; QListIterator<DotConstString> li(m_jobs); @@ -792,9 +843,26 @@ bool DotRunner::run() dotArgs+=' '; dotArgs+=s->data(); } - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; + dotArgs=QCString("\"")+m_file.data()+"\""; + bool redo = FALSE; + for (li.toFirst();(s=li.current());++li) + { + if (s->pdfData()) + { + if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error; + if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) + { + if (!resetPDFSize(width,height,s->pdfData())) goto error; + dotArgs+=' '; + dotArgs+=s->data(); + redo = TRUE; + } + } + } + if (redo) { - goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } else @@ -802,9 +870,15 @@ bool DotRunner::run() for (li.toFirst();(s=li.current());++li) { dotArgs=QCString("\"")+m_file.data()+"\" "+s->data(); - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; + if (s->pdfData()) { - goto error; + if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error; + if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) + { + if (!resetPDFSize(width,height,s->pdfData())) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; + } } } } @@ -3150,7 +3224,7 @@ QCString DotClassGraph::writeGraph(FTextStream &out, DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); if (usePDFLatex) { - dotRun->addJob("pdf",absPdfName); + dotRun->addJob("pdf",absPdfName,absBaseName); } else { @@ -3508,7 +3582,7 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out, DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); if (usePDFLatex) { - dotRun->addJob("pdf",absPdfName); + dotRun->addJob("pdf",absPdfName,absBaseName); } else { @@ -3826,7 +3900,7 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat graphForma DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); if (usePDFLatex) { - dotRun->addJob("pdf",absPdfName); + dotRun->addJob("pdf",absPdfName,absBaseName); } else { @@ -3992,7 +4066,7 @@ QCString DotDirDeps::writeGraph(FTextStream &out, DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); if (usePDFLatex) { - dotRun->addJob("pdf",absPdfName); + dotRun->addJob("pdf",absPdfName,absBaseName); } else { @@ -4170,7 +4244,7 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, { if (Config_getBool(USE_PDFLATEX)) { - dotRun.addJob("pdf",absOutFile+".pdf"); + dotRun.addJob("pdf",absOutFile+".pdf",absOutFile); } else { @@ -4555,7 +4629,7 @@ QCString DotGroupCollaboration::writeGraph( FTextStream &t, DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); if (usePDFLatex) { - dotRun->addJob("pdf",absPdfName); + dotRun->addJob("pdf",absPdfName,absBaseName); } else { @@ -42,6 +42,12 @@ class DotRunnerQueue; enum GraphOutputFormat { GOF_BITMAP, GOF_EPS }; enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook }; +// the graphicx LaTeX has a limitation of maximum size of 16384 +// To be on the save side we take it a little bit smaller i.e. 150 inch * 72 dpi +// It is anyway hard to view these size of images +#define MAX_LATEX_GRAPH_INCH 150 +#define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) + /** Attributes of an edge of a dot graph */ struct EdgeInfo { @@ -338,11 +344,12 @@ class DotGroupCollaboration class DotConstString { public: - DotConstString() { m_str=0; } - ~DotConstString() { delete[] m_str; } - DotConstString(const QCString &s) : m_str(0) { set(s); } - DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } + DotConstString() { m_str=0; m_pdfstr=0;} + ~DotConstString() { delete[] m_str; delete[] m_pdfstr;} + DotConstString(const QCString &s, const QCString &p = NULL) : m_str(0), m_pdfstr(0) { set(s); setpdf(p);} + DotConstString(const DotConstString &s) : m_str(0), m_pdfstr(0) { set(s.data()); } const char *data() const { return m_str; } + const char *pdfData() const { return m_pdfstr; } bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } void set(const QCString &s) { @@ -354,9 +361,20 @@ class DotConstString qstrcpy(m_str,s.data()); } } + void setpdf(const QCString &p) + { + delete[] m_pdfstr; + m_pdfstr=0; + if (!p.isEmpty()) + { + m_pdfstr=new char[p.length()+1]; + qstrcpy(m_pdfstr,p.data()); + } + } private: DotConstString &operator=(const DotConstString &); char *m_str; + char *m_pdfstr; }; /** Helper class to run dot from doxygen. @@ -377,7 +395,7 @@ class DotRunner /** Adds an additional job to the run. * Performing multiple jobs one file can be faster. */ - void addJob(const char *format,const char *output); + void addJob(const char *format,const char *output, const char *base = NULL); void addPostProcessing(const char *cmd,const char *args); |