Doxygen
Loading...
Searching...
No Matches
dotgraph.cpp
Go to the documentation of this file.
1/******************************************************************************
2*
3* Copyright (C) 1997-2019 by Dimitri van Heesch.
4*
5* Permission to use, copy, modify, and distribute this software and its
6* documentation under the terms of the GNU General Public License is hereby
7* granted. No representations are made about the suitability of this software
8* for any purpose. It is provided "as is" without express or implied warranty.
9* See the GNU General Public License for more details.
10*
11* Documents produced by Doxygen are derivative works derived from the
12* input used in their production; they are not affected by this license.
13*
14*/
15
16// own header
17#include "dotgraph.h"
18
19// standard includes
20#include <mutex>
21
22// other includes
23#include "config.h"
24#include "dot.h"
25#include "dotfilepatcher.h"
26#include "dotnode.h"
27#include "doxygen.h"
28#include "fileinfo.h"
29#include "indexlist.h"
30#include "md5hash.h"
31#include "message.h"
32#include "portable.h"
33#include "textstream.h"
34#include "util.h"
35
36//DString DotGraph::DOT_FONTNAME; // will be initialized in initDot
37//int DotGraph::DOT_FONTSIZE; // will be initialized in initDot
38
39/*! Checks if a file "baseName".md5 exists. If so the contents
40* are compared with \a md5. If equal false is returned.
41* The .md5 is created or updated after successful creation of the output file.
42*/
43static bool sameMd5Signature(const DString &baseName,
44 const DString &md5)
45{
46 bool same = false;
47 char md5stored[33];
48 md5stored[0]=0;
49 std::ifstream f = Portable::openInputStream(baseName+".md5",true);
50 if (f.is_open())
51 {
52 // read checksum
53 f.read(md5stored,32);
54 md5stored[32]='\0';
55 // compare checksum
56 if (!f.fail() && md5==md5stored)
57 {
58 same = true;
59 }
60 //printf("sameSignature(%s,%s==%s)=%d\n",qPrint(baseName),md5stored,qPrint(md5),same);
61 }
62 else
63 {
64 //printf("sameSignature(%s) not found\n",qPrint(baseName));
65 }
66 return same;
67}
68
69static bool deliverablesPresent(const DString &file1,const DString &file2)
70{
71 bool file1Ok = true;
72 bool file2Ok = true;
73 if (!file1.empty())
74 {
75 FileInfo fi(file1.str());
76 file1Ok = (fi.exists() && fi.size()>0);
77 }
78 if (!file2.empty())
79 {
80 FileInfo fi(file2.str());
81 file2Ok = (fi.exists() && fi.size()>0);
82 }
83 return file1Ok && file2Ok;
84}
85
86static bool insertMapFile(TextStream &out,const DString &mapFile,
87 const DString &relPath,const DString &mapLabel)
88{
89 FileInfo fi(mapFile.str());
90 if (fi.exists() && fi.size()>0) // reuse existing map file
91 {
92 TextStream t;
93 DotFilePatcher::convertMapFile(t,mapFile,relPath,false);
94 if (!t.empty())
95 {
96 out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">\n";
97 out << t.str();
98 out << "</map>\n";
99 }
100 return true;
101 }
102 return false; // no map file yet, need to generate it
103}
104
105//--------------------------------------------------------------------
106
108{
110 ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps"));
111}
112
114
116 TextStream& t, // output stream for the code file (html, ...)
117 GraphOutputFormat gf, // bitmap(png/svg) or ps(eps/pdf)
118 EmbeddedOutputFormat ef, // html, latex, ...
119 const DString &path, // output folder
120 const DString &fileName, // name of the code file (for code patcher)
121 const DString &relPath, // output folder relative to code file
122 bool generateImageMap, // in case of bitmap, shall there be code generated?
123 int graphId) // number of this graph in the current code, used in svg code
124{
125 m_graphFormat = gf;
126 m_textFormat = ef;
127 m_dir = Dir(path.str());
128 m_fileName = fileName;
129 m_relPath = relPath;
130 m_generateImageMap = generateImageMap;
131 m_graphId = graphId;
132
133 m_absPath = m_dir.absPath() + "/";
135
137
139
141 {
142 std::lock_guard<std::mutex> lock(g_dotIndexListMutex);
144 }
145
146 generateCode(t);
147
148 return m_baseName;
149}
150
152{
153 if (!m_dir.exists())
154 {
155 term("Output dir {} does not exist!\n", m_dir.path());
156 }
157
158 // calculate md5
159 DString sigStr = md5str(m_theGraph.view());
160
161 // already queued files are processed again in case the output format has changed
162
163 if (sameMd5Signature(absBaseName(), sigStr) &&
166 )
167 )
168 {
169 // all needed files are there
170 return false;
171 }
172
173 // need to rebuild the image
174
175 // write .dot file because image was new or has changed
176 std::ofstream f = Portable::openOutputStream(absDotName());
177 if (!f.is_open())
178 {
179 err("Could not open file {} for writing\n",absDotName());
180 return true;
181 }
182 f << m_theGraph;
183 f.close();
184
186 {
187 // run dot to create a bitmap image
189 }
191 {
192 // run dot to create a .eps image
193 if (Config_getBool(USE_PDFLATEX))
194 {
196 }
197 else
198 {
200 }
201 }
202 return true;
203}
204
206{
207 DString imgExt = getDotImageExtension();
209 {
210 t << "<para>\n";
211 t << " <informalfigure>\n";
212 t << " <mediaobject>\n";
213 t << " <imageobject>\n";
214 t << " <imagedata";
215 t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << imgExt << "\">";
216 t << "</imagedata>\n";
217 t << " </imageobject>\n";
218 t << " </mediaobject>\n";
219 t << " </informalfigure>\n";
220 t << "</para>\n";
221 }
222 else if (m_graphFormat==GraphOutputFormat::BITMAP && m_generateImageMap) // produce HTML to include the image
223 {
224 if (imgExt=="svg") // add link to SVG file without map file
225 {
226 if (!m_noDivTag) t << "<div class=\"center\">";
227 if (m_regenerate || !DotFilePatcher::writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file
228 {
229 if (m_regenerate)
230 {
232 createFilePatcher(absImgName())->
233 addSVGConversion(m_relPath,false,DString(),m_zoomable,m_graphId);
234 }
235 int mapId = DotManager::instance()->
236 createFilePatcher(m_fileName)->
237 addSVGObject(m_baseName,absImgName(),m_relPath);
238 t << "<!-- " << "SVG " << mapId << " -->";
239 }
240 if (!m_noDivTag) t << "</div>\n";
241 }
242 else // add link to bitmap file with image map
243 {
244 if (!m_noDivTag) t << "<div class=\"center\">";
245 t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#"
246 << DotFilePatcher::mapLabelToId(getMapLabel()) << "\" loading=\"lazy\" alt=\"" << getImgAltText() << "\"/>";
247 if (!m_noDivTag) t << "</div>";
248 t << "\n";
250 {
251 int mapId = DotManager::instance()->
252 createFilePatcher(m_fileName)->
254 t << "<!-- MAP " << mapId << " -->\n";
255 }
256 }
257 }
258 else if (m_graphFormat==GraphOutputFormat::EPS) // produce tex to include the .eps image
259 {
261 {
262 int figId = DotManager::instance()->
263 createFilePatcher(m_fileName)->
264 addFigure(m_baseName,absBaseName(),false /*true*/);
265 t << "\n% FIG " << figId << "\n";
266 }
267 }
268}
269
271{
272 t << "digraph ";
273 if (title.empty())
274 {
275 t << "\"Dot Graph\"";
276 }
277 else
278 {
279 t << "\"" << convertToXML(title) << "\"";
280 }
281 t << "\n{\n";
282 if (Config_getBool(INTERACTIVE_SVG)) // insert a comment to force regeneration when this
283 // option is toggled
284 {
285 t << " // INTERACTIVE_SVG=YES\n";
286 }
287 t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size replacement
288 t << " bgcolor=\"transparent\";\n";
289 DString c = Config_getString(DOT_COMMON_ATTR);
290 if (!c.empty()) c += ",";
291 t << " edge [" << c << Config_getString(DOT_EDGE_ATTR) << "];\n";
292 t << " node [" << c << Config_getString(DOT_NODE_ATTR) << "];\n";
293}
294
296{
297 t << "}\n";
298}
299
301 GraphType gt,
302 GraphOutputFormat format,
303 const DString &rank, // either "LR", "RL", or ""
304 bool renderParents,
305 bool backArrows,
306 const DString &title,
307 DString &graphStr)
308{
309 //printf("computeMd5Signature\n");
310 TextStream md5stream;
311 writeGraphHeader(md5stream,title);
312 if (!rank.empty())
313 {
314 md5stream << " rankdir=\"" << rank << "\";\n";
315 }
316 root->clearWriteFlag();
317 root->write(md5stream, gt, format, gt!=GraphType::CallGraph && gt!=GraphType::Dependency, true, backArrows);
318 if (renderParents)
319 {
320 for (const auto &pn : root->parents())
321 {
322 if (pn->isVisible())
323 {
324 const auto &children = pn->children();
325 auto child_it = std::find(children.begin(),children.end(),root);
326 size_t index = child_it - children.begin();
327 root->writeArrow(md5stream, // stream
328 gt, // graph type
329 format, // output format
330 pn, // child node
331 &pn->edgeInfo()[index], // edge info
332 false, // topDown?
333 backArrows // point back?
334 );
335 }
336 pn->write(md5stream, // stream
337 gt, // graph type
338 format, // output format
339 true, // topDown?
340 false, // toChildren?
341 backArrows // backward pointing arrows?
342 );
343 }
344 }
345 writeGraphFooter(md5stream);
346
347 graphStr=md5stream.str();
348}
349
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
std::string_view view() const
Definition dstring.h:162
size_t size() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:154
const std::string & str() const
Definition dstring.h:645
Class representing a directory in the file system.
Definition dir.h:73
std::string absPath() const
Definition dir.cpp:370
std::string path() const
Definition dir.cpp:240
bool exists() const
Definition dir.cpp:263
static DString mapLabelToId(const DString &mapLabel)
static bool writeVecGfxFigure(TextStream &out, const DString &baseName, const DString &figureName)
static bool writeSVGFigureLink(TextStream &out, const DString &relPath, const DString &baseName, const DString &absImgName)
Check if a reference to a SVG figure can be written and do so if possible.
static bool convertMapFile(TextStream &t, const DString &mapName, const DString &relPath, bool urlOnly=false, const DString &context=DString())
static void computeGraph(DotNode *root, GraphType gt, GraphOutputFormat format, const DString &rank, bool renderParents, bool backArrows, const DString &title, DString &graphStr)
Definition dotgraph.cpp:300
DString m_baseName
Definition dotgraph.h:94
bool m_noDivTag
Definition dotgraph.h:98
Dir m_dir
Definition dotgraph.h:87
int m_graphId
Definition dotgraph.h:91
EmbeddedOutputFormat m_textFormat
Definition dotgraph.h:86
DString m_theGraph
Definition dotgraph.h:95
static void writeGraphFooter(TextStream &t)
Definition dotgraph.cpp:295
bool m_urlOnly
Definition dotgraph.h:100
DString absDotName() const
Definition dotgraph.h:79
GraphOutputFormat m_graphFormat
Definition dotgraph.h:85
DString m_fileName
Definition dotgraph.h:88
void generateCode(TextStream &t)
Definition dotgraph.cpp:205
bool prepareDotFile()
Definition dotgraph.cpp:151
DString absImgName() const
Definition dotgraph.h:81
virtual DString getImgAltText() const
Definition dotgraph.h:74
virtual DString getBaseName() const =0
DString m_relPath
Definition dotgraph.h:89
bool m_doNotAddImageToIndex
Definition dotgraph.h:97
DString relImgName() const
Definition dotgraph.h:82
virtual DString getMapLabel() const =0
bool m_regenerate
Definition dotgraph.h:96
virtual DString absMapName() const
Definition dotgraph.h:72
bool m_zoomable
Definition dotgraph.h:99
DString writeGraph(TextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const DString &path, const DString &fileName, const DString &relPath, bool writeImageMap=true, int graphId=-1)
Definition dotgraph.cpp:115
DString m_absPath
Definition dotgraph.h:93
DString absBaseName() const
Definition dotgraph.h:78
DString imgName() const
Definition dotgraph.cpp:107
static void writeGraphHeader(TextStream &t, const DString &title=DString())
Definition dotgraph.cpp:270
virtual void computeTheGraph()=0
friend class DotNode
Definition dotgraph.h:36
bool m_generateImageMap
Definition dotgraph.h:90
void addJob(const DotJob &newJob)
Definition dot.cpp:92
static DotManager * instance()
Definition dot.cpp:78
void writeArrow(TextStream &t, GraphType gt, GraphOutputFormat f, const DotNode *cn, const EdgeInfo *ei, bool topDown, bool pointBack=true) const
Definition dotnode.cpp:605
void write(TextStream &t, GraphType gt, GraphOutputFormat f, bool topDown, bool toChildren, bool backArrows)
Definition dotnode.cpp:656
void clearWriteFlag()
Definition dotnode.cpp:887
const DotNodeRefVector & parents() const
Definition dotnode.h:123
static IndexList * indexList
Definition doxygen.h:125
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
bool exists() const
Definition fileinfo.cpp:34
size_t size() const
Definition fileinfo.cpp:27
void addImageFile(const DString &name)
Definition indexlist.h:124
Text streaming class that buffers data.
Definition textstream.h:36
bool empty() const
Returns true iff the buffer is empty.
Definition textstream.h:256
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:232
#define Config_getEnumAsString(name)
Definition config.h:36
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
static bool sameMd5Signature(const DString &baseName, const DString &md5)
Definition dotgraph.cpp:43
std::mutex g_dotIndexListMutex
Definition dotgraph.cpp:113
static bool deliverablesPresent(const DString &file1, const DString &file2)
Definition dotgraph.cpp:69
static bool insertMapFile(TextStream &out, const DString &mapFile, const DString &relPath, const DString &mapLabel)
Definition dotgraph.cpp:86
GraphType
Definition dotgraph.h:31
@ Dependency
Definition dotgraph.h:31
@ CallGraph
Definition dotgraph.h:31
EmbeddedOutputFormat
Definition dotgraph.h:30
GraphOutputFormat
Definition dotgraph.h:29
DString md5str(const std::string_view &str)
Definition md5hash.h:33
#define err(fmt,...)
Definition message.h:127
#define term(fmt,...)
Definition message.h:137
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:692
std::ofstream openOutputStream(const DString &name, bool append=false)
Definition portable.cpp:681
Portable versions of functions that are platform dependent.
DString convertToXML(const DString &s, bool keepEntities, const bool citeEntry)
Definition util.cpp:3232
DString getDotImageExtension()
Definition util.cpp:4964
A bunch of utility functions.