summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralbert-github <albert.tests@gmail.com>2018-04-26 13:15:23 (GMT)
committeralbert-github <albert.tests@gmail.com>2018-04-26 13:15:23 (GMT)
commit49079853fc4670c11b46e12eba7cb519608be8b0 (patch)
treed77a97380ebd683065035be53d4268fbe047e2d7
parente75de3722b98115f27483aeacb3b2b1dbe7114a3 (diff)
downloadDoxygen-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.cpp98
-rw-r--r--src/dot.h28
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
{
diff --git a/src/dot.h b/src/dot.h
index dce1a3a..ab6a316 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -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);