diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | addon/doxywizard/CMakeLists.txt | 1 | ||||
-rw-r--r-- | appveyor.yml | 4 | ||||
-rw-r--r-- | libmscgen/gd.c | 82 | ||||
-rw-r--r-- | libmscgen/gd_intern.h | 2 | ||||
-rw-r--r-- | libmscgen/mscgen_api.c | 4 | ||||
-rw-r--r-- | src/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/configimpl.l | 27 | ||||
-rw-r--r-- | src/doctokenizer.l | 11 | ||||
-rw-r--r-- | src/dot.cpp | 273 | ||||
-rw-r--r-- | src/dot.h | 41 | ||||
-rw-r--r-- | src/dotdirdeps.cpp | 8 | ||||
-rw-r--r-- | src/dotfilepatcher.cpp | 152 | ||||
-rw-r--r-- | src/dotfilepatcher.h | 21 | ||||
-rw-r--r-- | src/dotgraph.cpp | 101 | ||||
-rw-r--r-- | src/dotgraph.h | 9 | ||||
-rw-r--r-- | src/dotgroupcollaboration.cpp | 11 | ||||
-rw-r--r-- | src/dotlegendgraph.cpp | 72 | ||||
-rw-r--r-- | src/dotlegendgraph.h | 35 | ||||
-rw-r--r-- | src/dotnode.cpp | 4 | ||||
-rw-r--r-- | src/dotrunner.cpp | 18 | ||||
-rw-r--r-- | src/dotrunner.h | 8 | ||||
-rw-r--r-- | src/doxygen.cpp | 1 | ||||
-rw-r--r-- | src/formula.cpp | 18 | ||||
-rw-r--r-- | src/index.cpp | 7 | ||||
-rw-r--r-- | src/util.cpp | 6 |
26 files changed, 475 insertions, 460 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aa1c01..2644ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,8 @@ if (use_libclang) endif() endif() -# use C++11 standard for compiling (libclang option requires it) -set(CMAKE_CXX_STANDARD 11) +# use C++14 standard for compiling (libclang option requires it) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) diff --git a/addon/doxywizard/CMakeLists.txt b/addon/doxywizard/CMakeLists.txt index 5b1c9fa..6aacd8b 100644 --- a/addon/doxywizard/CMakeLists.txt +++ b/addon/doxywizard/CMakeLists.txt @@ -31,7 +31,6 @@ endif() include_directories( . ${CMAKE_SOURCE_DIR}/libversion - ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/qtools ${GENERATED_SRC} ) diff --git a/appveyor.yml b/appveyor.yml index d18474f..7969be0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,9 +29,9 @@ init: install: # Static url: https://github.com/MiKTeX/miktex/issues/321#issuecomment-496286866 # The setup is small enough, and does not need to be cached - - appveyor DownloadFile https://miktex.org/download/win/miktexsetup-x64.zip + - appveyor-retry appveyor DownloadFile https://miktex.org/download/win/miktexsetup-x64.zip - 7z e miktexsetup-x64.zip - - miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential download + - appveyor-retry miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential download - miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential --shared install - refreshenv - pip install conan diff --git a/libmscgen/gd.c b/libmscgen/gd.c index 7f0a258..da7731d 100644 --- a/libmscgen/gd.c +++ b/libmscgen/gd.c @@ -501,7 +501,7 @@ BGD_DECLARE(int) gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, i #define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;} #define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;} #define HWB_UNDEFINED -1 -#define SETUP_RGB(s, r, g, b) {s.R = r/255.0; s.G = g/255.0; s.B = b/255.0;} +#define SETUP_RGB(s, r, g, b) {s.R = r/255.0f; s.G = g/255.0f; s.B = b/255.0f;} #define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c))) @@ -567,7 +567,7 @@ HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2) if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED)) { diff = 0; /* Undefined hues always match... */ } else { - diff = fabs (HWB1.H - HWB2.H); + diff = fabsf(HWB1.H - HWB2.H); if (diff > 3) { diff = 6 - diff; /* Remember, it's a colour circle */ } @@ -1191,7 +1191,7 @@ clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim) *x0 = mindim; /* now, perhaps, adjust the far end of the line as well */ if (*x1 > maxdim) { - *y1 += m * (maxdim - *x1); + *y1 += (int)(m * (maxdim - *x1)); *x1 = maxdim; } return 1; @@ -1594,7 +1594,7 @@ BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, in TBB: but watch out for /0! */ double ac = cos (atan2 (dy, dx)); if (ac != 0) { - wid = thick / ac; + wid = (int)(thick / ac); } else { wid = 1; } @@ -1654,7 +1654,7 @@ BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, in TBB: but watch out for /0! */ double as = sin (atan2 (dy, dx)); if (as != 0) { - wid = thick / as; + wid = (int)(thick / as); } else { wid = 1; } @@ -1734,7 +1734,7 @@ BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int TBB: but watch out for /0! */ double as = sin (atan2 (dy, dx)); if (as != 0) { - wid = thick / as; + wid = (int)(thick / as); } else { wid = 1; } @@ -1783,7 +1783,7 @@ BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int TBB: but watch out for /0! */ double as = sin (atan2 (dy, dx)); if (as != 0) { - wid = thick / as; + wid = (int)(thick / as); } else { wid = 1; } @@ -3071,12 +3071,12 @@ BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, in } else { dc = gdImageGetPixel (dst, tox, toy); - ncR = gdImageRed (src, c) * (pct / 100.0) - + gdImageRed (dst, dc) * ((100 - pct) / 100.0); - ncG = gdImageGreen (src, c) * (pct / 100.0) - + gdImageGreen (dst, dc) * ((100 - pct) / 100.0); - ncB = gdImageBlue (src, c) * (pct / 100.0) - + gdImageBlue (dst, dc) * ((100 - pct) / 100.0); + ncR = (int)(gdImageRed (src, c) * (pct / 100.0) + + gdImageRed (dst, dc) * ((100 - pct) / 100.0)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0) + + gdImageGreen (dst, dc) * ((100 - pct) / 100.0)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0) + + gdImageBlue (dst, dc) * ((100 - pct) / 100.0)); /* Find a reasonable color */ nc = gdImageColorResolve (dst, ncR, ncG, ncB); @@ -3144,15 +3144,15 @@ BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX nc = c; } else { dc = gdImageGetPixel (dst, tox, toy); - g = 0.29900 * gdImageRed(dst, dc) - + 0.58700 * gdImageGreen(dst, dc) + 0.11400 * gdImageBlue(dst, dc); + g = 0.29900f * gdImageRed(dst, dc) + + 0.58700f * gdImageGreen(dst, dc) + 0.11400f * gdImageBlue(dst, dc); - ncR = gdImageRed (src, c) * (pct / 100.0) - + g * ((100 - pct) / 100.0); - ncG = gdImageGreen (src, c) * (pct / 100.0) - + g * ((100 - pct) / 100.0); - ncB = gdImageBlue (src, c) * (pct / 100.0) - + g * ((100 - pct) / 100.0); + ncR = (int)(gdImageRed (src, c) * (pct / 100.0) + + g * ((100 - pct) / 100.0)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0) + + g * ((100 - pct) / 100.0)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0) + + g * ((100 - pct) / 100.0)); /* First look for an exact match */ nc = gdImageColorExact (dst, ncR, ncG, ncB); @@ -3378,14 +3378,14 @@ BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst, for (dx = dstX - radius; (dx <= dstX + radius); dx++) { double sxd = (dx - dstX) * aCos - (dy - dstY) * aSin; double syd = (dy - dstY) * aCos + (dx - dstX) * aSin; - int sx = sxd + scX; - int sy = syd + scY; + int sx = (int)(sxd + scX); + int sy = (int)(syd + scY); if ((sx >= srcX) && (sx < srcX + srcWidth) && (sy >= srcY) && (sy < srcY + srcHeight)) { int c = gdImageGetPixel (src, sx, sy); /* 2.0.34: transparency wins */ if (c == src->transparent) { - gdImageSetPixel (dst, dx, dy, dst->transparent); + gdImageSetPixel (dst, (int)dx, (int)dy, dst->transparent); } else if (!src->trueColor) { /* Use a table to avoid an expensive lookup on every single pixel */ @@ -3399,10 +3399,10 @@ BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst, gdImageAlpha (src, c)); } - gdImageSetPixel (dst, dx, dy, cmap[c]); + gdImageSetPixel (dst, (int)dx, (int)dy, cmap[c]); } else { gdImageSetPixel (dst, - dx, dy, + (int)dx, (int)dy, gdImageColorResolveAlpha (dst, gdImageRed (src, c), @@ -3469,16 +3469,16 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, for (x = dstX; (x < dstX + dstW); x++) { float sy1, sy2, sx1, sx2; float sx, sy; - float spixels = 0.0; - float red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0; - float alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0; + float spixels = 0.0f; + float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; + float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f; sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH; sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH; sy = sy1; do { float yportion; if (floorf(sy) == floorf(sy1)) { - yportion = 1.0 - (sy - floorf(sy)); + yportion = 1.0f - (sy - floorf(sy)); if (yportion > sy2 - sy1) { yportion = sy2 - sy1; } @@ -3486,7 +3486,7 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, } else if (sy == floorf(sy2)) { yportion = sy2 - floorf(sy2); } else { - yportion = 1.0; + yportion = 1.0f; } sx1 = ((float)(x - dstX)) * (float) srcW / dstW; sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW; @@ -3496,7 +3496,7 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, float pcontribution; int p; if (floorf(sx) == floorf(sx1)) { - xportion = 1.0 - (sx - floorf(sx)); + xportion = 1.0f - (sx - floorf(sx)); if (xportion > sx2 - sx1) { xportion = sx2 - sx1; } @@ -3504,7 +3504,7 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, } else if (sx == floorf(sx2)) { xportion = sx2 - floorf(sx2); } else { - xportion = 1.0; + xportion = 1.0f; } pcontribution = xportion * yportion; p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY); @@ -3517,14 +3517,14 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, alpha_sum += alpha_factor; contrib_sum += pcontribution; spixels += xportion * yportion; - sx += 1.0; + sx += 1.0f; } while (sx < sx2); sy += 1.0f; } while (sy < sy2); - if (spixels != 0.0) { + if (spixels != 0.0f) { red /= spixels; green /= spixels; blue /= spixels; @@ -3539,14 +3539,14 @@ BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, blue /= alpha_sum; } /* Clamping to allow for rounding errors above */ - if (red > 255.0) { - red = 255.0; + if (red > 255.0f) { + red = 255.0f; } - if (green > 255.0) { - green = 255.0; + if (green > 255.0f) { + green = 255.0f; } if (blue > 255.0f) { - blue = 255.0; + blue = 255.0f; } if (alpha > gdAlphaMax) { alpha = gdAlphaMax; @@ -4373,7 +4373,7 @@ static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int co * This isn't a problem as computed dy/dx values came from ints above. */ ag = fabs(abs((int)dy) < abs((int)dx) ? cos(atan2(dy, dx)) : sin(atan2(dy, dx))); if (ag != 0) { - wid = thick / ag; + wid = (int)(thick / ag); } else { wid = 1; } diff --git a/libmscgen/gd_intern.h b/libmscgen/gd_intern.h index 2e7264b..c9d7f2e 100644 --- a/libmscgen/gd_intern.h +++ b/libmscgen/gd_intern.h @@ -58,7 +58,7 @@ uchar_clamp(double clr, unsigned char max) { result = (clr < 0) ? 0 : max; }/* if */ - return result; + return (unsigned char)result; }/* uchar_clamp*/ diff --git a/libmscgen/mscgen_api.c b/libmscgen/mscgen_api.c index 0f6052a..31f5556 100644 --- a/libmscgen/mscgen_api.c +++ b/libmscgen/mscgen_api.c @@ -1329,7 +1329,7 @@ static void arcLine(Context *ctx, /* Get co-ordinates of the arc end-point */ ADrawComputeArcPoint(sx, y - 1, ctx->opts.entitySpacing - 8, - ctx->opts.loopArcHeight, 180 - 45, + ctx->opts.loopArcHeight, 180.0f - 45.0f, &px, &py); /* Draw a cross */ @@ -1393,7 +1393,7 @@ static void arcLine(Context *ctx, /* Get co-ordinates of the arc end-point */ ADrawComputeArcPoint(sx, y - 1, ctx->opts.entitySpacing - 8, - ctx->opts.loopArcHeight, 45, + ctx->opts.loopArcHeight, 45.0f, &px, &py); /* Draw a cross */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 029b613..7e54b2b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,16 +216,17 @@ add_library(_doxygen STATIC docparser.cpp docsets.cpp dot.cpp - dotcallgraph.cpp - dotclassgraph.cpp - dotdirdeps.cpp - dotfilepatcher.cpp + dotcallgraph.cpp + dotlegendgraph.cpp + dotclassgraph.cpp + dotdirdeps.cpp + dotfilepatcher.cpp dotgfxhierarchytable.cpp dotgraph.cpp - dotgroupcollaboration.cpp - dotincldepgraph.cpp + dotgroupcollaboration.cpp + dotincldepgraph.cpp dotnode.cpp - dotrunner.cpp + dotrunner.cpp doxygen.cpp eclipsehelp.cpp emoji.cpp diff --git a/src/configimpl.l b/src/configimpl.l index eaf6cf4..7d22859 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -30,6 +30,7 @@ #include <qregexp.h> #include <qstack.h> #include <qglobal.h> +#include <qthread.h> #include "configimpl.h" #include "version.h" @@ -1533,6 +1534,7 @@ void Config::checkAndCorrect() // dotImageFormat = "png"; //} + // correct DOT_FONTNAME if needed QCString &dotFontName=Config_getString(DOT_FONTNAME); if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf") { @@ -1540,7 +1542,32 @@ void Config::checkAndCorrect() "You may want to clear or change DOT_FONTNAME.\n" "Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n"); } + else if (dotFontName.isEmpty()) + { + dotFontName = "Helvetica"; + } + // clip dotFontSize against the maximum bounds + int &dotFontSize = Config_getInt(DOT_FONTSIZE); + if (dotFontSize<4) + { + dotFontSize=4; + } + else if (dotFontSize>24) + { + dotFontSize=24; + } + + // clip number of threads + int &dotNumThreads = Config_getInt(DOT_NUM_THREADS); + if (dotNumThreads>32) + { + dotNumThreads=32; + } + else if (dotNumThreads<=0) + { + dotNumThreads=QMAX(2,QThread::idealThreadCount()+1); + } // check dot path QCString &dotPath = Config_getString(DOT_PATH); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index fdc6968..9786720 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -354,8 +354,9 @@ ATTRNAME [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]* ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))? URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=] URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+ -FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+@&#] -FILEECHAR [a-z_A-Z0-9\-\+@&#] +URLPROTOCOL ("http:"|"https:"|"ftp:"|"file:"|"news:"|"irc") +FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#] +FILEECHAR [a-z_A-Z0-9\-\+&#] HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)+ FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK} LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? @@ -625,17 +626,17 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } return TK_COMMAND_SEL(); } -<St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}/\. { // URL. +<St_Para>{URLPROTOCOL}{URLMASK}/\. { // URL. g_token->name=yytext; g_token->isEMailAddr=FALSE; return TK_URL; } -<St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK} { // URL +<St_Para>{URLPROTOCOL}{URLMASK} { // URL g_token->name=yytext; g_token->isEMailAddr=FALSE; return TK_URL; } -<St_Para>"<"("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}">" { // URL +<St_Para>"<"{URLPROTOCOL}{URLMASK}">" { // URL g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); g_token->isEMailAddr=FALSE; 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 << "\">"; @@ -18,66 +18,43 @@ #include <qlist.h> #include <qdict.h> -#include <qwaitcondition.h> -#include <qmutex.h> -#include <qqueue.h> -#include <qthread.h> +#include <qcstring.h> + #include "sortdict.h" -#include "qgstring.h" -#include "qdir.h" -#include "qcstring.h" -#include "dotgraph.h" + +#include "dotgraph.h" // only for GraphOutputFormat #include "dotfilepatcher.h" #include "dotrunner.h" class FTextStream; class DotRunner; class DotRunnerQueue; -class DotWorkerThread; -/** Singleton that manages dot relation actions */ +/** Singleton that manages parallel dot invocations and patching files for embedding image maps */ class DotManager { public: static DotManager *instance(); - DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); - int addMap(const QCString &file,const QCString &mapFile, - const QCString &relPath,bool urlOnly, - const QCString &context,const QCString &label); - int addFigure(const QCString &file,const QCString &baseName, - const QCString &figureName,bool heightCheck); - int addSVGConversion(const QCString &file,const QCString &relPath, - bool urlOnly,const QCString &context,bool zoomable,int graphId); - int addSVGObject(const QCString &file,const QCString &baseName, - const QCString &figureNAme,const QCString &relPath); - bool run(); + DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); + DotFilePatcher *createFilePatcher(const QCString &fileName); + bool run() const; private: DotManager(); virtual ~DotManager(); QDict<DotRunner> m_runners; - SDict<DotFilePatcher> m_dotMaps; + SDict<DotFilePatcher> m_filePatchers; static DotManager *m_theInstance; DotRunnerQueue *m_queue; QList<DotWorkerThread> m_workers; }; -void initDot(); - -/** Generated a graphs legend page */ -void generateGraphLegend(const char *path); - void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format); void writeDotImageMapFromFile(FTextStream &t, const QCString& inFile, const QCString& outDir, const QCString& relPath,const QCString& baseName, const QCString& context,int graphId=-1); -bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName); -bool convertMapFile(FTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE, - const QCString &context=QCString()); #endif diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp index 85906d1..98c7ca7 100644 --- a/src/dotdirdeps.cpp +++ b/src/dotdirdeps.cpp @@ -22,14 +22,16 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph \"" << dd->displayName() << "\" {\n"; if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=transparent;\n"; } t << " compound=true\n"; - t << " node [ fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", fontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; - t << " edge [ labelfontsize=\"" << DotGraph::DOT_FONTSIZE << "\", labelfontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; + t << " node [ fontsize=\"" << fontSize << "\", fontname=\"" << fontName << "\"];\n"; + t << " edge [ labelfontsize=\"" << fontSize << "\", labelfontname=\"" << fontName << "\"];\n"; QDict<DirDef> dirsInGraph(257); @@ -39,7 +41,7 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" << dd->parent()->shortName() - << "\" fontname=\"" << DotGraph::DOT_FONTNAME << "\", fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", URL=\""; + << "\" fontname=\"" << fontName << "\", fontsize=\"" << fontSize << "\", URL=\""; t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; t << "\"]\n"; } diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 91b7c78..92a5618 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -14,6 +14,7 @@ */ #include "dotfilepatcher.h" +#include "dotrunner.h" #include "qstring.h" #include "config.h" @@ -209,7 +210,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, * map file was found * \returns TRUE if successful. */ -bool convertMapFile(FTextStream &t,const char *mapName, +bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName, const QCString relPath, bool urlOnly, const QCString &context) { @@ -255,9 +256,9 @@ DotFilePatcher::DotFilePatcher(const char *patchFile) m_maps.setAutoDelete(TRUE); } -QCString DotFilePatcher::file() const +bool DotFilePatcher::isSVGFile() const { - return m_patchFile; + return m_patchFile.right(4)==".svg"; } int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, @@ -320,7 +321,7 @@ int DotFilePatcher::addSVGObject(const QCString &baseName, return id; } -bool DotFilePatcher::run() +bool DotFilePatcher::run() const { //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); bool interactiveSVG_local = Config_getBool(INTERACTIVE_SVG); @@ -479,7 +480,7 @@ bool DotFilePatcher::run() 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()); - if (!DotGraph::writeVecGfxFigure(t,map->label,map->mapFile)) + if (!writeVecGfxFigure(t,map->label,map->mapFile)) { err("problem writing FIG %d figure!\n",mapId); return FALSE; @@ -537,3 +538,144 @@ bool DotFilePatcher::run() QDir::current().remove(tmpName); return TRUE; } + +//--------------------------------------------------------------------------------------------- + + +// 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 do so if possible. +/// Returns FALSE if not possible (for instance because the SVG file is not yet generated). +bool DotFilePatcher::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; +} + +bool DotFilePatcher::writeVecGfxFigure(FTextStream &out,const QCString &baseName, + const QCString &figureName) +{ + int width=400,height=550; + if (Config_getBool(USE_PDFLATEX)) + { + if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + else + { + if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + //printf("Got PDF/EPS size %d,%d\n",width,height); + int maxWidth = 350; /* approx. page width in points, excl. margins */ + int maxHeight = 550; /* 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; +} diff --git a/src/dotfilepatcher.h b/src/dotfilepatcher.h index dd5c511..b68208d 100644 --- a/src/dotfilepatcher.h +++ b/src/dotfilepatcher.h @@ -19,21 +19,37 @@ #include "qcstring.h" #include "qlist.h" +class FTextStream; + /** Helper class to insert a set of map file into an output file */ class DotFilePatcher { public: DotFilePatcher(const char *patchFile); + int addMap(const QCString &mapFile,const QCString &relPath, bool urlOnly,const QCString &context,const QCString &label); + int addFigure(const QCString &baseName, const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly, const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &baseName, const QCString &figureName, const QCString &relPath); - bool run(); - QCString file() const; + bool run() const; + bool isSVGFile() const; + + static bool convertMapFile(FTextStream &t,const char *mapName, + const QCString relPath, bool urlOnly=FALSE, + const QCString &context=QCString()); + + static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName); + + static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, + const QCString& figureName); private: struct Map @@ -50,4 +66,5 @@ class DotFilePatcher QCString m_patchFile; }; + #endif diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index ca6bcca..df64d66 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -24,11 +24,12 @@ #include "dotrunner.h" #include "dotgraph.h" #include "dotnode.h" +#include "dotfilepatcher.h" #define MAP_CMD "cmapx" -QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot -int DotGraph::DOT_FONTSIZE; // will be initialized in initDot +//QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot +//int DotGraph::DOT_FONTSIZE; // will be initialized in initDot /*! Checks if a file "baseName".md5 exists. If so the contents * are compared with \a md5. If equal FALSE is returned. @@ -90,7 +91,7 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, { QGString tmpstr; FTextStream tmpout(&tmpstr); - convertMapFile(tmpout,mapFile,relPath,FALSE); + DotFilePatcher::convertMapFile(tmpout,mapFile,relPath,FALSE); if (!tmpstr.isEmpty()) { out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl; @@ -104,12 +105,10 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, //-------------------------------------------------------------------- -QCString DotGraph::IMG_EXT; - QCString DotGraph::imgName() const { return m_baseName + ((m_graphFormat == GOF_BITMAP) ? - ("." + IMG_EXT) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); + ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); } QCString DotGraph::writeGraph( @@ -209,6 +208,7 @@ bool DotGraph::prepareDotFile() void DotGraph::generateCode(FTextStream &t) { + QCString imgExt = getDotImageExtension(); if (m_graphFormat==GOF_BITMAP && m_textFormat==EOF_DocBook) { t << "<para>" << endl; @@ -216,7 +216,7 @@ void DotGraph::generateCode(FTextStream &t) t << " <mediaobject>" << endl; t << " <imageobject>" << endl; t << " <imagedata"; - t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << IMG_EXT << "\">"; + t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << imgExt << "\">"; t << "</imagedata>" << endl; t << " </imageobject>" << endl; t << " </mediaobject>" << endl; @@ -225,16 +225,20 @@ void DotGraph::generateCode(FTextStream &t) } else if (m_graphFormat==GOF_BITMAP && m_generateImageMap) // produce HTML to include the image { - if (IMG_EXT=="svg") // add link to SVG file without map file + if (imgExt=="svg") // add link to SVG file without map file { if (!m_noDivTag) t << "<div class=\"center\">"; - if (m_regenerate || !writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file + if (m_regenerate || !DotFilePatcher::writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file { if (m_regenerate) { - DotManager::instance()->addSVGConversion(absImgName(),m_relPath,FALSE,QCString(),m_zoomable,m_graphId); + DotManager::instance()-> + createFilePatcher(absImgName())-> + addSVGConversion(m_relPath,FALSE,QCString(),m_zoomable,m_graphId); } - int mapId = DotManager::instance()->addSVGObject(m_fileName,m_baseName,absImgName(),m_relPath); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addSVGObject(m_baseName,absImgName(),m_relPath); t << "<!-- SVG " << mapId << " -->" << endl; } if (!m_noDivTag) t << "</div>" << endl; @@ -247,16 +251,20 @@ void DotGraph::generateCode(FTextStream &t) t << endl; if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) { - int mapId = DotManager::instance()->addMap(m_fileName, absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addMap(absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); t << "<!-- MAP " << mapId << " -->" << endl; } } } else if (m_graphFormat==GOF_EPS) // produce tex to include the .eps image { - if (m_regenerate || !writeVecGfxFigure(t,m_baseName,absBaseName())) + if (m_regenerate || !DotFilePatcher::writeVecGfxFigure(t,m_baseName,absBaseName())) { - int figId = DotManager::instance()->addFigure(m_fileName,m_baseName,absBaseName(),FALSE /*TRUE*/); + int figId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addFigure(m_baseName,absBaseName(),FALSE /*TRUE*/); t << endl << "% FIG " << figId << endl; } } @@ -264,6 +272,8 @@ void DotGraph::generateCode(FTextStream &t) void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -284,12 +294,12 @@ void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\"," - "labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\",shape=record];\n"; + t << " edge [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\"," + "labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\",shape=record];\n"; } void DotGraph::writeGraphFooter(FTextStream &t) @@ -347,54 +357,3 @@ void DotGraph::computeGraph(DotNode *root, graphStr=buf.data(); } -bool DotGraph::writeVecGfxFigure(FTextStream &out,const QCString &baseName, - const QCString &figureName) -{ - int width=400,height=550; - if (Config_getBool(USE_PDFLATEX)) - { - if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - else - { - if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - //printf("Got PDF/EPS size %d,%d\n",width,height); - int maxWidth = 350; /* approx. page width in points, excl. margins */ - int maxHeight = 550; /* 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; -} diff --git a/src/dotgraph.h b/src/dotgraph.h index 27d6938..0eda3a8 100644 --- a/src/dotgraph.h +++ b/src/dotgraph.h @@ -34,11 +34,6 @@ class DotGraph DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {} virtual ~DotGraph() {} - static QCString DOT_FONTNAME; // will be initialized in initDot - static int DOT_FONTSIZE; // will be initialized in initDot - - static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, const QCString& figureName); - protected: /** returns node numbers. The Counter is reset by the constructor */ int getNextNodeNumber() { return ++m_curNodeNumber; } @@ -72,10 +67,6 @@ class DotGraph virtual void computeTheGraph() = 0; - static QCString IMG_EXT; - - friend void initDot(); - QCString absBaseName() const { return m_absPath + m_baseName; } QCString absDotName() const { return m_absPath + m_baseName + ".dot"; } QCString imgName() const; diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index be55ac0..f9a11e7 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -356,9 +356,10 @@ bool DotGroupCollaboration::isTrivial() const return m_usedNodes->count() <= 1; } -void DotGroupCollaboration::writeGraphHeader(FTextStream &t, - const QCString &title) const +void DotGroupCollaboration::writeGraphHeader(FTextStream &t,const QCString &title) const { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -374,8 +375,8 @@ void DotGroupCollaboration::writeGraphHeader(FTextStream &t, { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\",labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\",shape=box];\n"; + t << " edge [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\",labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\",shape=box];\n"; t << " rankdir=LR;\n"; } diff --git a/src/dotlegendgraph.cpp b/src/dotlegendgraph.cpp new file mode 100644 index 0000000..98e1f88 --- /dev/null +++ b/src/dotlegendgraph.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 by Dimitri van Heesch. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation under the terms of the GNU General Public License is hereby +* granted. No representations are made about the suitability of this software +* for any purpose. It is provided "as is" without express or implied warranty. +* See the GNU General Public License for more details. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotlegendgraph.h" +#include "util.h" +#include "config.h" +#include "doxygen.h" +#include "dot.h" +#include "language.h" +#include "dotfilepatcher.h" + +void DotLegendGraph::writeGraph(const char *path) +{ + FTextStream ts; + DotGraph::writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); + + if (getDotImageExtension()=="svg") + { + DotManager::instance()-> + createFilePatcher(absBaseName()+Config_getString(HTML_FILE_EXTENSION))-> + addSVGObject("graph_legend", absImgName(),QCString()); + } +} + +QCString DotLegendGraph::getBaseName() const +{ + return "graph_legend"; +} + +void DotLegendGraph::computeTheGraph() +{ + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,theTranslator->trLegendTitle()); + 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\"];\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\"];\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\"];\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\"];\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\"];\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\"];\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\"];\n"; + writeGraphFooter(md5stream); +} + +QCString DotLegendGraph::getMapLabel() const +{ + return ""; +} + diff --git a/src/dotlegendgraph.h b/src/dotlegendgraph.h new file mode 100644 index 0000000..2d8eeec --- /dev/null +++ b/src/dotlegendgraph.h @@ -0,0 +1,35 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 by Dimitri van Heesch. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation under the terms of the GNU General Public License is hereby +* granted. No representations are made about the suitability of this software +* for any purpose. It is provided "as is" without express or implied warranty. +* See the GNU General Public License for more details. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTLEGENDGRAPH_H +#define DOTLEGENDGRAPH_H + +#include "dotgraph.h" + +/** Representation of a legend explaining the meaning of boxes, arrows, and colors */ +class DotLegendGraph : public DotGraph +{ + public: + void writeGraph(const char *path); + + private: + virtual QCString getBaseName() const; + virtual void computeTheGraph(); + virtual QCString getMapLabel() const; + +}; + +#endif + diff --git a/src/dotnode.cpp b/src/dotnode.cpp index ae06fb2..491bcb5 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -540,7 +540,7 @@ void DotNode::writeArrow(FTextStream &t, if (pointBack && !umlUseArrow) t << "dir=\"back\","; t << "color=\"" << eProps->edgeColorMap[ei->color()] - << "\",fontsize=\"" << DotGraph::DOT_FONTSIZE << "\","; + << "\",fontsize=\"" << Config_getInt(DOT_FONTSIZE) << "\","; t << "style=\"" << eProps->edgeStyleMap[ei->style()] << "\""; if (!ei->label().isEmpty()) { @@ -559,7 +559,7 @@ void DotNode::writeArrow(FTextStream &t, t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\""; } - if (format==GOF_BITMAP) t << ",fontname=\"" << DotGraph::DOT_FONTNAME << "\""; + if (format==GOF_BITMAP) t << ",fontname=\"" << Config_getString(DOT_FONTNAME) << "\""; t << "];" << endl; } diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index 3a621c7..c01a4e5 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -28,6 +28,7 @@ #define MAX_LATEX_GRAPH_INCH 150 #define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) +//----------------------------------------------------------------------------------------- // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. @@ -142,12 +143,11 @@ bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool return FALSE; } -bool DotRunner::DOT_CLEANUP; -bool DotRunner::DOT_MULTI_TARGETS; -DotConstString DotRunner::DOT_EXE; +//--------------------------------------------------------------------------------- DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash) - : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(DOT_CLEANUP) + : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(Config_getBool(DOT_CLEANUP)), + m_dotExe(Config_getString(DOT_PATH)+"dot") { m_jobs.setAutoDelete(TRUE); } @@ -183,7 +183,7 @@ bool DotRunner::run() DotJob *s; // create output - if (DOT_MULTI_TARGETS) + if (Config_getBool(DOT_MULTI_TARGETS)) { dotArgs=QCString("\"")+m_file.data()+"\""; for (li.toFirst();(s=li.current());++li) @@ -191,14 +191,14 @@ bool DotRunner::run() dotArgs+=' '; dotArgs+=s->args.data(); } - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } else { for (li.toFirst();(s=li.current());++li) { dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -214,7 +214,7 @@ bool DotRunner::run() { if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error; dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -245,7 +245,7 @@ bool DotRunner::run() return TRUE; error: err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", - exitCode,DOT_EXE.data(),dotArgs.data()); + exitCode,m_dotExe.data(),dotArgs.data()); return FALSE; } diff --git a/src/dotrunner.h b/src/dotrunner.h index 4128fe8..1b68c18 100644 --- a/src/dotrunner.h +++ b/src/dotrunner.h @@ -34,7 +34,6 @@ class DotConstString DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } const char *data() const { return m_str; } bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } - void init(const char *s) { set(s); } private: void set(char const* s) @@ -101,14 +100,9 @@ class DotRunner private: DotConstString m_file; DotConstString m_md5Hash; + DotConstString m_dotExe; bool m_cleanUp; QList<DotJob> m_jobs; - - static bool DOT_CLEANUP; - static bool DOT_MULTI_TARGETS; - static DotConstString DOT_EXE; - friend void initDot(); - }; /** Queue of dot jobs to run. */ diff --git a/src/doxygen.cpp b/src/doxygen.cpp index a6455fc..f8e54de 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -11680,7 +11680,6 @@ void generateOutput() } initSearchIndexer(); - initDot(); bool generateHtml = Config_getBool(GENERATE_HTML); bool generateLatex = Config_getBool(GENERATE_LATEX); diff --git a/src/formula.cpp b/src/formula.cpp index 1c5042e..534f56a 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -118,11 +118,12 @@ void FormulaList::generateBitmaps(const char *path) int pageNum=*pagePtr; msg("Generating image form_%d.png for formula\n",pageNum); char dviArgs[4096]; + char psArgs[4096]; QCString formBase; formBase.sprintf("_form%d",pageNum); // run dvips to convert the page with number pageIndex to an - // encapsulated postscript. - sprintf(dviArgs,"-q -D 600 -E -n 1 -p %d -o %s.eps _formulas.dvi", + // postscript file. + sprintf(dviArgs,"-q -D 600 -n 1 -p %d -o %s_tmp.ps _formulas.dvi", pageIndex,formBase.data()); portable_sysTimerStart(); if (portable_system("dvips",dviArgs)!=0) @@ -133,6 +134,18 @@ void FormulaList::generateBitmaps(const char *path) return; } portable_sysTimerStop(); + // run ps2epsi to convert to an encapsulated postscript file with + // boundingbox (dvips with -E has some problems here). + sprintf(psArgs,"%s_tmp.ps %s.eps",formBase.data(),formBase.data()); + portable_sysTimerStart(); + if (portable_system("ps2epsi",psArgs)!=0) + { + err("Problems running ps2epsi. Check your installation!\n"); + portable_sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } + portable_sysTimerStop(); // now we read the generated postscript file to extract the bounding box QFileInfo fi(formBase+".eps"); if (fi.exists()) @@ -282,6 +295,7 @@ void FormulaList::generateBitmaps(const char *path) f.close(); } // remove intermediate image files + thisDir.remove(formBase+"_tmp.ps"); thisDir.remove(formBase+".eps"); thisDir.remove(formBase+".pnm"); thisDir.remove(formBase+".ps"); diff --git a/src/index.cpp b/src/index.cpp index 0631ee4..f5faea4 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -41,6 +41,7 @@ #include "ftvhelp.h" #include "dot.h" #include "dotgfxhierarchytable.h" +#include "dotlegendgraph.h" #include "pagedef.h" #include "dirdef.h" #include "vhdldocgen.h" @@ -3919,7 +3920,9 @@ void writeGraphInfo(OutputList &ol) if (!Config_getBool(HAVE_DOT) || !Config_getBool(GENERATE_HTML)) return; ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - generateGraphLegend(Config_getString(HTML_OUTPUT)); + + DotLegendGraph gd; + gd.writeGraph(Config_getString(HTML_OUTPUT)); bool &stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS); bool oldStripCommentsState = stripCommentsStateRef; @@ -3944,7 +3947,7 @@ void writeGraphInfo(OutputList &ol) legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e); //printf("legendDocs=%s\n",legendDocs.data()); } - FileDef *fd = createFileDef("","graph_legend"); + FileDef *fd = createFileDef("","graph_legend.dox"); ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE); delete fd; diff --git a/src/util.cpp b/src/util.cpp index 8816de1..4dc7c71 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -9051,9 +9051,9 @@ bool mainPageHasTitle() QCString getDotImageExtension(void) { - QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); - imgExt = imgExt.replace( QRegExp(":.*"), "" ); - return imgExt; + QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); + int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format + return i==-1 ? imgExt : imgExt.left(i); } bool openOutputFile(const char *outFile,QFile &f) |