Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package doxygen for openSUSE:Factory checked in at 2023-03-17 17:00:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/doxygen (Old) and /work/SRC/openSUSE:Factory/.doxygen.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "doxygen" Fri Mar 17 17:00:54 2023 rev:91 rq:1072283 version:1.9.6 Changes: -------- --- /work/SRC/openSUSE:Factory/doxygen/doxygen.changes 2022-12-29 13:09:11.828964562 +0100 +++ /work/SRC/openSUSE:Factory/.doxygen.new.31432/doxygen.changes 2023-03-17 17:00:56.512636541 +0100 @@ -1,0 +2,10 @@ +Thu Mar 16 02:17:05 UTC 2023 - Stefan Brüns <stefan.bru...@rwth-aachen.de> + +- Fix boundingbox parsing of graphviz PDFs when using cairo >= + 1.17.6, add: + * Fix-boundingbox-parsing_part1.patch + * Fix-boundingbox-parsing_part2.patch + * Fix-boundingbox-parsing_part3.patch + * Fix-boundingbox-parsing_part4.patch + +------------------------------------------------------------------- New: ---- Fix-boundingbox-parsing_part1.patch Fix-boundingbox-parsing_part2.patch Fix-boundingbox-parsing_part3.patch Fix-boundingbox-parsing_part4.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ doxygen.spec ++++++ --- /var/tmp/diff_new_pack.Dml3uU/_old 2023-03-17 17:00:57.468641550 +0100 +++ /var/tmp/diff_new_pack.Dml3uU/_new 2023-03-17 17:00:57.472641571 +0100 @@ -1,7 +1,7 @@ # # spec file for package doxygen # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -34,6 +34,11 @@ Patch1: %{name}-no-lowercase-man-names.patch # The unified libclang-cpp library doesn't exist on older Leap / SLE Patch10: doxygen-no-libclang-cpp.patch +# Fix PDF boudingbox parsing when dot uses cairo >= 1.17.6 -- https://github.com/doxygen/doxygen/issues/9319 +Patch20: https://github.com/doxygen/doxygen/commit/966d69c603b5.patch#/Fix-boundingbox-parsing_part1.patch +Patch21: https://github.com/doxygen/doxygen/commit/7b2a6027775b.patch#/Fix-boundingbox-parsing_part2.patch +Patch22: https://github.com/doxygen/doxygen/commit/f3514d578633.patch#/Fix-boundingbox-parsing_part3.patch +Patch23: https://github.com/doxygen/doxygen/commit/8129939c312e.patch#/Fix-boundingbox-parsing_part4.patch BuildRequires: bison BuildRequires: cmake >= 2.8.12 BuildRequires: flex @@ -68,6 +73,10 @@ %patch10 -p1 %endif %endif +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 %build %cmake \ ++++++ doxywizard.spec ++++++ --- /var/tmp/diff_new_pack.Dml3uU/_old 2023-03-17 17:00:57.488641654 +0100 +++ /var/tmp/diff_new_pack.Dml3uU/_new 2023-03-17 17:00:57.492641675 +0100 @@ -1,7 +1,7 @@ # # spec file for package doxywizard # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed ++++++ Fix-boundingbox-parsing_part1.patch ++++++ ++++ 1815 lines (skipped) ++++++ Fix-boundingbox-parsing_part2.patch ++++++ >From 7b2a6027775b0158304635a98de0f9b5672f163a Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch <doxy...@gmail.com> Date: Wed, 4 Jan 2023 10:55:36 +0100 Subject: [PATCH] issue #9319: Doc build fails with cairo 1.17.6 --- TinyDeflate/gunzip.hh | 26 ++++++----- src/CMakeLists.txt | 1 + src/dotrunner.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++ src/doxygen.cpp | 2 - 4 files changed, 120 insertions(+), 13 deletions(-) diff --git a/TinyDeflate/gunzip.hh b/TinyDeflate/gunzip.hh index c0039d5f832..c237298fdb0 100644 --- a/TinyDeflate/gunzip.hh +++ b/TinyDeflate/gunzip.hh @@ -944,23 +944,27 @@ namespace gunzip_ns // The following routines are macros rather than e.g. lambda functions, // in order to make them inlined in the function structure, and breakable/resumable. + #define CONCAT(a, b) a##b // Bit-by-bit input routine - #define DummyGetBits(numbits) do { \ - auto p = state.template GetBits<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), numbits); \ - if((Abortable & Flag_InputAbortable) && !~p) return -2; \ + #define DummyGetBits_(line,numbits) do { \ + auto CONCAT(pd,line) = state.template GetBits<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), numbits); \ + if((Abortable & Flag_InputAbortable) && !~CONCAT(pd,line)) return -2; \ } while(0) + #define DummyGetBits(numbits) DummyGetBits_(__LINE__, numbits) - #define GetBits(numbits, target) \ - auto p = state.template GetBits<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), numbits); \ - if((Abortable & Flag_InputAbortable) && !~p) return -2; \ - target = p + #define GetBits_(line,numbits, target) \ + auto CONCAT(pb,line) = state.template GetBits<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), numbits); \ + if((Abortable & Flag_InputAbortable) && !~CONCAT(pb,line)) return -2; \ + target = CONCAT(pb,line) + #define GetBits(numbits, target) GetBits_(__LINE__, numbits, target) // Huffman tree read routine. - #define HuffRead(tree, target) \ - auto p = state.template HuffRead<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), tree); \ - if((Abortable & Flag_InputAbortable) && !~p) return -2; \ - target = p + #define HuffRead_(line, tree, target) \ + auto CONCAT(ph,line) = state.template HuffRead<bool(Abortable&Flag_InputAbortable)>(std::forward<InputFunctor>(input), tree); \ + if((Abortable & Flag_InputAbortable) && !~CONCAT(ph,line)) return -2; \ + target = CONCAT(ph,line) + #define HuffRead(tree, target) HuffRead_(__LINE__, tree, target) #define Fail_If(condition) do { \ /*assert(!(condition));*/ \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e9df895ce3a..0e33638c42d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ # vim:ts=4:sw=4:expandtab:autoindent: include_directories( + ${PROJECT_SOURCE_DIR}/TinyDeflate ${PROJECT_SOURCE_DIR}/filesystem ${PROJECT_SOURCE_DIR}/libmd5 ${PROJECT_SOURCE_DIR}/liblodepng diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index d3b2615f4ed..5be9f20de9c 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -16,6 +16,8 @@ #include <cassert> #include <cmath> +#include <gunzip.hh> + #include "dotrunner.h" #include "util.h" #include "portable.h" @@ -31,6 +33,9 @@ #define MAX_LATEX_GRAPH_INCH 150 #define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) +//#define DBG(x) printf x +#define DBG(x) do {} while(0) + //----------------------------------------------------------------------------------------- // 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) bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height,bool isEps) { +#if 0 const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; size_t bblen = strlen(bb); FILE *f = Portable::fopen(fileName,"rb"); @@ -139,6 +145,104 @@ bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height, err("Failed to extract bounding box from generated diagram file %s\n",qPrint(fileName)); fclose(f); return FALSE; +#endif + std::ifstream f = Portable::openInputStream(fileName); + if (!f.is_open()) + { + err("Failed to open file %s for extracting bounding box\n",qPrint(fileName)); + return false; + } + + // read file contents into string 'contents' + std::stringstream buffer; + buffer << f.rdbuf(); + std::string contents = buffer.str(); + + // start of bounding box marker we are looking for + const std::string boundingBox = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; + + // helper routine to extract the bounding boxes width and height + auto extractBoundingBox = [&fileName,&boundingBox,&width,&height](const char *s) -> bool + { + int x,y; + double w,h; + if (sscanf(s+boundingBox.length(),"%d %d %lf %lf",&x,&y,&w,&h)==4) + { + *width = static_cast<int>(std::ceil(w)); + *height = static_cast<int>(std::ceil(h)); + return true; + } + err("Failed to extract bounding box from generated diagram file %s\n",qPrint(fileName)); + return false; + }; + + // compressed segment start and end markers + const std::string streamStart = "stream\n"; + const std::string streamEnd = "\nendstream"; + + const size_t l = contents.length(); + size_t i=0; + while (i<l) + { + if (!isEps && contents[i]=='s' && strncmp(&contents[i],streamStart.c_str(),streamStart.length())==0) + { // compressed stream start + int col=17; + i+=streamStart.length(); + const size_t start=i; + DBG(("---- start stream at offset %08x\n",(int)i)); + while (i<l) + { + if (contents[i]=='\n' && strncmp(&contents[i],streamEnd.c_str(),streamEnd.length())==0) + { // compressed block found in range [start..i] + DBG(("\n---- end stream at offset %08x\n",(int)i)); + // decompress it into decompressBuf + std::vector<char> decompressBuf; + const char *source = &contents[start]; + const size_t sourceLen = i-start; + size_t sourcePos = 0; + decompressBuf.reserve(sourceLen*2); + auto getter = [source,&sourcePos,sourceLen]() -> int { + return sourcePos<sourceLen ? static_cast<unsigned char>(source[sourcePos++]) : EOF; + }; + auto putter = [&decompressBuf](const char c) -> int { + decompressBuf.push_back(c); return c; + }; + Deflate(getter,putter); + // convert decompression buffer to string + std::string s(decompressBuf.begin(), decompressBuf.end()); + DBG(("decompressed_data=[[[\n%s\n]]]\n",s.c_str())); + // search for bounding box marker + const size_t idx = s.find(boundingBox); + if (idx!=std::string::npos) // found bounding box in uncompressed data + { + return extractBoundingBox(s.c_str()+idx); + } + // continue searching after end stream marker + i+=streamEnd.length(); + break; + } + else // compressed stream character + { + if (col>16) { col=0; DBG(("\n%08x: ",static_cast<int>(i))); } + DBG(("%02x ",static_cast<unsigned char>(contents[i]))); + col++; + i++; + } + } + } + else if (((isEps && contents[i]=='%') || (!isEps && contents[i]=='/')) && + strncmp(&contents[i],boundingBox.c_str(),boundingBox.length())==0) + { // uncompressed bounding box + return extractBoundingBox(&contents[i]); + } + else // uncompressed stream character + { + i++; + } + } + err("Failed to find bounding box in generated diagram file %s\n",qPrint(fileName)); + // nothing found + return false; } //--------------------------------------------------------------------------------- diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 78b72ebfecc..55068e74dcb 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -11930,8 +11930,6 @@ void parseInput() { Portable::setenv("DOTFONTPATH",qPrint(curFontPath)); } - // issue 9319 - Portable::setenv("CAIRO_DEBUG_PDF","1"); } ++++++ Fix-boundingbox-parsing_part3.patch ++++++ >From f3514d578633cad3e39d6787f81085e46bafbaf4 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch <doxy...@gmail.com> Date: Wed, 4 Jan 2023 22:49:00 +0100 Subject: [PATCH] Fix and work around compiler warnings and remove dead code --- TinyDeflate/gunzip.hh | 4 ++-- src/dotrunner.cpp | 42 +++++++++--------------------------------- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/TinyDeflate/gunzip.hh b/TinyDeflate/gunzip.hh index c237298fdb0..a631815a255 100644 --- a/TinyDeflate/gunzip.hh +++ b/TinyDeflate/gunzip.hh @@ -430,7 +430,7 @@ namespace gunzip_ns static_assert((T)false, "result_of<CallableType> is invalid; use " "result_of<CallableType(zero or more argument types)> instead."); }; - #if __cplusplus > 202000UL + #if __cplusplus > 201703UL template <typename F, typename... Args> struct result_of<F(Args...)> : std::invoke_result<F, Args...> {}; #else @@ -702,7 +702,7 @@ namespace gunzip_ns // Note: Throws away progress already made traversing the tree return ~std::uint_least32_t(0); // error flag } - cur = (unsigned(cur) << 1) | bool(p); + cur = (unsigned(cur) << 1) | unsigned(bool(p)); #ifdef DEFL_DO_HUFF_STATS if(len > maxlen) { diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index 5be9f20de9c..9246029cb61 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -16,7 +16,16 @@ #include <cassert> #include <cmath> +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4242 ) +#pragma warning( disable : 4244 ) +#endif #include <gunzip.hh> +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + #include "dotrunner.h" #include "util.h" @@ -113,39 +122,6 @@ static bool resetPDFSize(const int width,const int height, const QCString &base) bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height,bool isEps) { -#if 0 - const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; - size_t bblen = strlen(bb); - FILE *f = Portable::fopen(fileName,"rb"); - if (!f) - { - //printf("readBoundingBox: could not open %s\n",fileName); - return FALSE; - } - const int maxLineLen=1024; - char buf[maxLineLen]; - while (fgets(buf,maxLineLen,f)!=NULL) - { - const char *p = strstr(buf,bb); - if (p) // found PageBoundingBox or /MediaBox string - { - int x,y; - double w,h; - fclose(f); - if (sscanf(p+bblen,"%d %d %lf %lf",&x,&y,&w,&h)!=4) - { - //printf("readBoundingBox sscanf fail\n"); - return FALSE; - } - *width = static_cast<int>(std::ceil(w)); - *height = static_cast<int>(std::ceil(h)); - return TRUE; - } - } - err("Failed to extract bounding box from generated diagram file %s\n",qPrint(fileName)); - fclose(f); - return FALSE; -#endif std::ifstream f = Portable::openInputStream(fileName); if (!f.is_open()) { ++++++ Fix-boundingbox-parsing_part4.patch ++++++ >From 8129939c312e4b5060042fdb93bd071b7b133381 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch <doxy...@gmail.com> Date: Thu, 5 Jan 2023 11:16:24 +0100 Subject: [PATCH] issue #9319: Doc build fails with cairo 1.17.6 - Improve detection of "flate" encoded streams --- TinyDeflate/gunzip.hh | 2 +- src/dotrunner.cpp | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/TinyDeflate/gunzip.hh b/TinyDeflate/gunzip.hh index a631815a255..652058ab823 100644 --- a/TinyDeflate/gunzip.hh +++ b/TinyDeflate/gunzip.hh @@ -430,7 +430,7 @@ namespace gunzip_ns static_assert((T)false, "result_of<CallableType> is invalid; use " "result_of<CallableType(zero or more argument types)> instead."); }; - #if __cplusplus > 201703UL + #if __cplusplus > 202000UL template <typename F, typename... Args> struct result_of<F(Args...)> : std::invoke_result<F, Args...> {}; #else diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index 9246029cb61..2e87a0d4a37 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -20,6 +20,7 @@ #pragma warning( push ) #pragma warning( disable : 4242 ) #pragma warning( disable : 4244 ) +#pragma warning( disable : 4996 ) #endif #include <gunzip.hh> #ifdef _MSC_VER @@ -156,11 +157,28 @@ bool DotRunner::readBoundingBox(const QCString &fileName,int *width,int *height, const std::string streamStart = "stream\n"; const std::string streamEnd = "\nendstream"; + auto detectDeflateStreamStart = [&streamStart](const char *s) + { + size_t len = streamStart.length(); + bool streamOK = strncmp(s,streamStart.c_str(),len)==0; + if (streamOK) // ASCII marker matches, check stream header bytes as well + { + unsigned short header1 = static_cast<unsigned char>(s[len])<<8; // CMF byte + if (header1) // not end of string + { + unsigned short header = (static_cast<unsigned char>(s[len+1])) | header1; // FLG byte + // check for correct header (see https://www.rfc-editor.org/rfc/rfc1950) + return ((header&0x8F20)==0x0800) && (header%31)==0; + } + } + return false; + }; + const size_t l = contents.length(); size_t i=0; while (i<l) { - if (!isEps && contents[i]=='s' && strncmp(&contents[i],streamStart.c_str(),streamStart.length())==0) + if (!isEps && contents[i]=='s' && detectDeflateStreamStart(&contents[i])) { // compressed stream start int col=17; i+=streamStart.length();