|
16 | 16 | #include <cassert>
|
17 | 17 | #include <cmath>
|
18 | 18 |
|
| 19 | +#include <gunzip.hh> |
| 20 | + |
19 | 21 | #include "dotrunner.h"
|
20 | 22 | #include "util.h"
|
21 | 23 | #include "portable.h"
|
|
31 | 33 | #define MAX_LATEX_GRAPH_INCH 150
|
32 | 34 | #define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72)
|
33 | 35 |
|
| 36 | +//#define DBG(x) printf x |
| 37 | +#define DBG(x) do {} while(0) |
| 38 | + |
34 | 39 | //-----------------------------------------------------------------------------------------
|
35 | 40 |
|
36 | 41 | // since dot silently reproduces the input file when it does not
|
@@ -108,6 +113,7 @@ static bool resetPDFSize(const int width,const int height, const QCString &base)
|
108 | 113 |
|
109 | 114 | bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height,bool isEps)
|
110 | 115 | {
|
| 116 | +#if 0 |
111 | 117 | const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox [";
|
112 | 118 | size_t bblen = strlen(bb);
|
113 | 119 | FILE *f = Portable::fopen(fileName,"rb");
|
@@ -139,6 +145,104 @@ bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height,
|
139 | 145 | err("Failed to extract bounding box from generated diagram file %s\n",qPrint(fileName));
|
140 | 146 | fclose(f);
|
141 | 147 | return FALSE;
|
| 148 | +#endif |
| 149 | + std::ifstream f = Portable::openInputStream(fileName); |
| 150 | + if (!f.is_open()) |
| 151 | + { |
| 152 | + err("Failed to open file %s for extracting bounding box\n",qPrint(fileName)); |
| 153 | + return false; |
| 154 | + } |
| 155 | + |
| 156 | + // read file contents into string 'contents' |
| 157 | + std::stringstream buffer; |
| 158 | + buffer << f.rdbuf(); |
| 159 | + std::string contents = buffer.str(); |
| 160 | + |
| 161 | + // start of bounding box marker we are looking for |
| 162 | + const std::string boundingBox = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; |
| 163 | + |
| 164 | + // helper routine to extract the bounding boxes width and height |
| 165 | + auto extractBoundingBox = [&fileName,&boundingBox,&width,&height](const char *s) -> bool |
| 166 | + { |
| 167 | + int x,y; |
| 168 | + double w,h; |
| 169 | + if (sscanf(s+boundingBox.length(),"%d %d %lf %lf",&x,&y,&w,&h)==4) |
| 170 | + { |
| 171 | + *width = static_cast<int>(std::ceil(w)); |
| 172 | + *height = static_cast<int>(std::ceil(h)); |
| 173 | + return true; |
| 174 | + } |
| 175 | + err("Failed to extract bounding box from generated diagram file %s\n",qPrint(fileName)); |
| 176 | + return false; |
| 177 | + }; |
| 178 | + |
| 179 | + // compressed segment start and end markers |
| 180 | + const std::string streamStart = "stream\n"; |
| 181 | + const std::string streamEnd = "\nendstream"; |
| 182 | + |
| 183 | + const size_t l = contents.length(); |
| 184 | + size_t i=0; |
| 185 | + while (i<l) |
| 186 | + { |
| 187 | + if (!isEps && contents[i]=='s' && strncmp(&contents[i],streamStart.c_str(),streamStart.length())==0) |
| 188 | + { // compressed stream start |
| 189 | + int col=17; |
| 190 | + i+=streamStart.length(); |
| 191 | + const size_t start=i; |
| 192 | + DBG(("---- start stream at offset %08x\n",(int)i)); |
| 193 | + while (i<l) |
| 194 | + { |
| 195 | + if (contents[i]=='\n' && strncmp(&contents[i],streamEnd.c_str(),streamEnd.length())==0) |
| 196 | + { // compressed block found in range [start..i] |
| 197 | + DBG(("\n---- end stream at offset %08x\n",(int)i)); |
| 198 | + // decompress it into decompressBuf |
| 199 | + std::vector<char> decompressBuf; |
| 200 | + const char *source = &contents[start]; |
| 201 | + const size_t sourceLen = i-start; |
| 202 | + size_t sourcePos = 0; |
| 203 | + decompressBuf.reserve(sourceLen*2); |
| 204 | + auto getter = [source,&sourcePos,sourceLen]() -> int { |
| 205 | + return sourcePos<sourceLen ? static_cast<unsigned char>(source[sourcePos++]) : EOF; |
| 206 | + }; |
| 207 | + auto putter = [&decompressBuf](const char c) -> int { |
| 208 | + decompressBuf.push_back(c); return c; |
| 209 | + }; |
| 210 | + Deflate(getter,putter); |
| 211 | + // convert decompression buffer to string |
| 212 | + std::string s(decompressBuf.begin(), decompressBuf.end()); |
| 213 | + DBG(("decompressed_data=[[[\n%s\n]]]\n",s.c_str())); |
| 214 | + // search for bounding box marker |
| 215 | + const size_t idx = s.find(boundingBox); |
| 216 | + if (idx!=std::string::npos) // found bounding box in uncompressed data |
| 217 | + { |
| 218 | + return extractBoundingBox(s.c_str()+idx); |
| 219 | + } |
| 220 | + // continue searching after end stream marker |
| 221 | + i+=streamEnd.length(); |
| 222 | + break; |
| 223 | + } |
| 224 | + else // compressed stream character |
| 225 | + { |
| 226 | + if (col>16) { col=0; DBG(("\n%08x: ",static_cast<int>(i))); } |
| 227 | + DBG(("%02x ",static_cast<unsigned char>(contents[i]))); |
| 228 | + col++; |
| 229 | + i++; |
| 230 | + } |
| 231 | + } |
| 232 | + } |
| 233 | + else if (((isEps && contents[i]=='%') || (!isEps && contents[i]=='/')) && |
| 234 | + strncmp(&contents[i],boundingBox.c_str(),boundingBox.length())==0) |
| 235 | + { // uncompressed bounding box |
| 236 | + return extractBoundingBox(&contents[i]); |
| 237 | + } |
| 238 | + else // uncompressed stream character |
| 239 | + { |
| 240 | + i++; |
| 241 | + } |
| 242 | + } |
| 243 | + err("Failed to find bounding box in generated diagram file %s\n",qPrint(fileName)); |
| 244 | + // nothing found |
| 245 | + return false; |
142 | 246 | }
|
143 | 247 |
|
144 | 248 | //---------------------------------------------------------------------------------
|
|
0 commit comments