external/afdko/UnpackedTarball_afdko.mk | 3 external/afdko/noverbose.patch | 56 ++++++++++++ vcl/source/gdi/embeddedfontsafdko.cxx | 146 +++++++++++++++++++++++--------- 3 files changed, 167 insertions(+), 38 deletions(-)
New commits: commit d701d7526dae6a693e201f7a4df59538f8b0c338 Author: Caolán McNamara <[email protected]> AuthorDate: Tue Oct 28 11:27:07 2025 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Oct 28 14:00:27 2025 +0100 throw exception on afdko error Change-Id: I41aee3390988d178f3a011d58589e09e6c6209a4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193089 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/vcl/source/gdi/embeddedfontsafdko.cxx b/vcl/source/gdi/embeddedfontsafdko.cxx index f6fcfbfd3180..a2b83cdb4161 100644 --- a/vcl/source/gdi/embeddedfontsafdko.cxx +++ b/vcl/source/gdi/embeddedfontsafdko.cxx @@ -84,6 +84,12 @@ static void suppressDebugMessagess(txCtx h) #endif } +static void txFatalCallback(txCtx h) +{ + txFree(h); + throw std::runtime_error("fatal tx error"); +} + // System afdko could be used by calling: tx -dump src dest here bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& destFileUrl) { @@ -100,6 +106,9 @@ bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& d txCtx h = txNew(nullptr); if (!h) return false; + // appSpecificFree is only called on error so we can piggyback on that + // to intercept what would otherwise be a fatal error + h->appSpecificFree = txFatalCallback; suppressDebugMessagess(h); OString srcFontPathA(srcFontPath.toUtf8()); @@ -109,14 +118,21 @@ bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& d h->src.stm.filename = const_cast<char*>(srcFontPathA.getStr()); h->dst.stm.filename = const_cast<char*>(destFilePathA.getStr()); - bool result = convertTx(h); - txFree(h); - return result; + try + { + bool result = convertTx(h); + txFree(h); + return result; + } + catch (const std::exception& e) + { + SAL_WARN("vcl.fonts", "tx failure: " << e.what()); + } #else (void)srcFontUrl; (void)destFileUrl; - return false; #endif + return false; } // System afdko could be used by calling: tx -t1 src dest here @@ -135,6 +151,9 @@ bool EmbeddedFontsManager::tx_t1(const OUString& srcFontUrl, const OUString& des txCtx h = txNew(nullptr); if (!h) return false; + // appSpecificFree is only called on error so we can piggyback on that + // to intercept what would otherwise be a fatal error + h->appSpecificFree = txFatalCallback; suppressDebugMessagess(h); setMode(h, mode_t1); @@ -143,14 +162,27 @@ bool EmbeddedFontsManager::tx_t1(const OUString& srcFontUrl, const OUString& des h->src.stm.filename = const_cast<char*>(srcFontPathA.getStr()); OString destFilePathA(destFilePath.toUtf8()); h->dst.stm.filename = const_cast<char*>(destFilePathA.getStr()); - bool result = convertTx(h); - txFree(h); - return result; + try + { + bool result = convertTx(h); + txFree(h); + return result; + } + catch (const std::exception& e) + { + SAL_WARN("vcl.fonts", "tx failure: " << e.what()); + } #else (void)srcFontUrl; (void)destFileUrl; - return false; #endif + return false; +} + +static void mergeFontsFatalCallback(txCtx h) +{ + mergeFontsFree(h); + throw std::runtime_error("fatal mergeFonts error"); } // System afdko could be used by calling: mergefonts -cid cidfontinfo destfile [glyphaliasfile mergefontfile]+ here @@ -188,6 +220,9 @@ bool EmbeddedFontsManager::mergefonts(const OUString& cidFontInfoUrl, const OUSt txCtx h = mergeFontsNew(nullptr); if (!h) return false; + // appSpecificFree is only called on error so we can piggyback on that + // to intercept what would otherwise be a fatal error + h->appSpecificFree = mergeFontsFatalCallback; suppressDebugMessagess(h); OString cidFontInfoPathA(cidFontInfoPath.toUtf8()); @@ -199,42 +234,49 @@ bool EmbeddedFontsManager::mergefonts(const OUString& cidFontInfoUrl, const OUSt SAL_INFO("vcl.fonts", "mergefonts -cid " << cidFontInfoPathA << " " << destFilePathA << aBuffer.toString()); - readCIDFontInfo(h, const_cast<char*>(cidFontInfoPathA.getStr())); + try + { + readCIDFontInfo(h, const_cast<char*>(cidFontInfoPathA.getStr())); - setMode(h, mode_cff); + setMode(h, mode_cff); - dstFileSetName(h, const_cast<char*>(destFilePathA.getStr())); - h->cfw.flags |= CFW_CHECK_IF_GLYPHS_DIFFER; - h->cfw.flags |= CFW_PRESERVE_GLYPH_ORDER; + dstFileSetName(h, const_cast<char*>(destFilePathA.getStr())); + h->cfw.flags |= CFW_CHECK_IF_GLYPHS_DIFFER; + h->cfw.flags |= CFW_PRESERVE_GLYPH_ORDER; - std::vector<char*> args; - for (const auto& path : paths) + std::vector<char*> args; + for (const auto& path : paths) + { + args.push_back(const_cast<char*>(path.getStr())); + } + // merge the input fonts into destfile + size_t resultarg = doMergeFileSet(h, args.size(), args.data(), 0); + SAL_WARN_IF(resultarg != args.size() - 1, "vcl.fonts", + "suspicious doMergeFileSet result of: " << resultarg); + + // convert that merged cid result to Type 1 + h->src.stm.filename = const_cast<char*>(destFilePathA.getStr()); + OString tmpdestfile = destFilePathA + ".temp"; + h->dst.stm.filename = const_cast<char*>(tmpdestfile.getStr()); + setMode(h, mode_t1); + bool result = convertTx(h); + mergeFontsFree(h); + + remove(destFilePathA.getStr()); + rename(tmpdestfile.getStr(), destFilePathA.getStr()); + + return result; + } + catch (const std::exception& e) { - args.push_back(const_cast<char*>(path.getStr())); + SAL_WARN("vcl.fonts", "mergeFonts failure: " << e.what()); } - // merge the input fonts into destfile - size_t resultarg = doMergeFileSet(h, args.size(), args.data(), 0); - SAL_WARN_IF(resultarg != args.size() - 1, "vcl.fonts", - "suspicious doMergeFileSet result of: " << resultarg); - - // convert that merged cid result to Type 1 - h->src.stm.filename = const_cast<char*>(destFilePathA.getStr()); - OString tmpdestfile = destFilePathA + ".temp"; - h->dst.stm.filename = const_cast<char*>(tmpdestfile.getStr()); - setMode(h, mode_t1); - bool result = convertTx(h); - mergeFontsFree(h); - - remove(destFilePathA.getStr()); - rename(tmpdestfile.getStr(), destFilePathA.getStr()); - - return result; #else (void)cidFontInfoUrl; (void)destFileUrl; (void)fonts; - return false; #endif + return false; } #if HAVE_FEATURE_AFDKO commit 433ec9a29575cd1f1ee89b1ea46aaefd2a5b4e39 Author: Caolán McNamara <[email protected]> AuthorDate: Wed Oct 22 13:43:02 2025 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Oct 28 14:00:19 2025 +0100 suppress verbose output Change-Id: I56141b7ed0ca9b1885ad7bc39a40d7bb0a730d7c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192859 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193088 Tested-by: Caolán McNamara <[email protected]> diff --git a/external/afdko/UnpackedTarball_afdko.mk b/external/afdko/UnpackedTarball_afdko.mk index 9cf0d6c50397..8989baf2eccd 100644 --- a/external/afdko/UnpackedTarball_afdko.mk +++ b/external/afdko/UnpackedTarball_afdko.mk @@ -26,8 +26,9 @@ $(eval $(call gb_UnpackedTarball_add_patches,afdko, \ external/afdko/extern_mergefonts.patch \ external/afdko/extern_makeotf.patch \ external/afdko/warnings.patch \ - external/afdko/antlr4-chrono.patch \ external/afdko/mergeFonts_crash.patch \ + external/afdko/noverbose.patch \ + external/afdko/antlr4-chrono.patch \ external/afdko/ubsan.patch.0 \ )) diff --git a/external/afdko/noverbose.patch b/external/afdko/noverbose.patch new file mode 100644 index 000000000000..4173d973dc67 --- /dev/null +++ b/external/afdko/noverbose.patch @@ -0,0 +1,56 @@ +--- afdko/c/mergefonts/source/mergeFonts.c 2025-10-22 13:47:13.840056699 +0100 ++++ afdko/c/mergefonts/source/mergeFonts.c 2025-10-22 13:48:02.496428544 +0100 +@@ -1727,7 +1727,9 @@ + for (j = 0; j < mergeInfo->newiFDArray.cnt; j++) { + if (curMaxFD < mergeInfo->newiFDArray.array[j]) { + curMaxFD = mergeInfo->newiFDArray.array[j]; +- fprintf(stderr, "Adding font dict %d from %s. ", curMaxFD, h->src.stm.filename); ++ if (h->flags & SHOW_NAMES) { ++ fprintf(stderr, "Adding font dict %d from %s. ", curMaxFD, h->src.stm.filename); ++ } + } + } + +--- afdko/c/makeotf/include/hotconv.h 2025-10-22 14:51:54.161381982 +0100 ++++ afdko/c/makeotf/include/hotconv.h 2025-10-22 14:57:50.948032645 +0100 +@@ -383,6 +383,7 @@ + #define HOT_SUBSET (1<<13) + #define HOT_SUPRESS__WIDTH_OPT (1<<14) /* suppress width optimization in CFF: makes it easier to poke at charstrings with other tools */ + #define HOT_VERBOSE (1<<15) /* Print all warnings and notes: else suppress the most annoying ones. */ ++#define HOT_SUPRESS_WARNINGS (1<<16) /* Print standard warnings and notes: else suppress the standard warnings. */ + + struct hotReadFontOverrides_ /* Record for instructions to modify font as it is read in. */ + { +--- afdko/c/makeotf/lib/hotconv/hot.c 2025-10-22 14:51:49.995353104 +0100 ++++ afdko/c/makeotf/lib/hotconv/hot.c 2025-10-22 14:56:10.084139451 +0100 +@@ -324,7 +324,9 @@ + + /* Convert to CFF */ + tcflags = 0; +- tcflags |= TC_DO_WARNINGS; ++ if (!(flags & HOT_SUPRESS_WARNINGS)) { ++ tcflags |= TC_DO_WARNINGS; ++ } + if (flags & HOT_ADD_AUTH_AREA) { + tcflags |= TC_ADDAUTHAREA; + } +@@ -385,7 +385,9 @@ + fi->FontName.length); + g->font.FontName.array[fi->FontName.length] = ' + g->font.FontName.cnt = fi->FontName.length + 1; +- hotMsg(g, hotHEADING, "processing font <%s>", g->font.FontName.array); ++ if (!(flags & HOT_SUPRESS_WARNINGS)) { ++ hotMsg(g, hotHEADING, "processing font <%s>", g->font.FontName.array); ++ } + + /* Copy basic font information */ + g->font.Notice = fi->Notice; +@@ -1444,7 +1444,7 @@ + /* Print note, error, warning, or fatal message (from note buffer is fmt is + NULL). If note used, handle reuse of g->note. */ + void CDECL hotMsg(hotCtx g, int level, const char *fmt, ...) { +- if (g->cb.message != NULL) { ++ if (g->cb.message != NULL && g->convertFlags & HOT_CONVERT_VERBOSE) { + // int lenName = g->font.FontName.cnt + 2; + + if (fmt == NULL) { diff --git a/vcl/source/gdi/embeddedfontsafdko.cxx b/vcl/source/gdi/embeddedfontsafdko.cxx index a6db3f3fe070..f6fcfbfd3180 100644 --- a/vcl/source/gdi/embeddedfontsafdko.cxx +++ b/vcl/source/gdi/embeddedfontsafdko.cxx @@ -25,6 +25,8 @@ #include "afdko.hxx" +#define SUPERVERBOSE 0 + static bool convertTx(txCtx h) { h->src.stm.fp = fopen(h->src.stm.filename, "rb"); @@ -65,6 +67,23 @@ static bool convertTx(txCtx h) } #endif +static void suppressDebugMessagess(txCtx h) +{ +#if !SUPERVERBOSE + h->t1r.dbg.fp = nullptr; + h->cfr.dbg.fp = nullptr; + h->svr.dbg.fp = nullptr; + h->ufr.dbg.fp = nullptr; + h->ufow.dbg.fp = nullptr; + h->ttr.dbg.fp = nullptr; + h->cfw.dbg.fp = nullptr; + h->t1w.dbg.fp = nullptr; + h->svw.dbg.fp = nullptr; +#else + (void)h; +#endif +} + // System afdko could be used by calling: tx -dump src dest here bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& destFileUrl) { @@ -81,6 +100,7 @@ bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& d txCtx h = txNew(nullptr); if (!h) return false; + suppressDebugMessagess(h); OString srcFontPathA(srcFontPath.toUtf8()); OString destFilePathA(destFilePath.toUtf8()); @@ -115,6 +135,7 @@ bool EmbeddedFontsManager::tx_t1(const OUString& srcFontUrl, const OUString& des txCtx h = txNew(nullptr); if (!h) return false; + suppressDebugMessagess(h); setMode(h, mode_t1); @@ -167,6 +188,7 @@ bool EmbeddedFontsManager::mergefonts(const OUString& cidFontInfoUrl, const OUSt txCtx h = mergeFontsNew(nullptr); if (!h) return false; + suppressDebugMessagess(h); OString cidFontInfoPathA(cidFontInfoPath.toUtf8()); OString destFilePathA(destFilePath.toUtf8()); @@ -277,18 +299,26 @@ bool EmbeddedFontsManager::makeotf(const OUString& srcFontUrl, const OUString& d OString featuresPathA(featuresPath.toUtf8()); SAL_INFO( - "vcl.fonts", "makeotf -mf " + "vcl.fonts", "makeotf -nshw -mf " << fontMenuNameDBPathA << " -f " << srcFontPathA << " -o " << destFilePathA << (!charMapPathA.isEmpty() ? " -ch "_ostr + charMapPathA : OString()) << (!featuresPathA.isEmpty() ? " -ff "_ostr + featuresPathA : OString())); cbFCDBRead(cbctx, const_cast<char*>(fontMenuNameDBPathA.getStr())); - cbConvert(cbctx, HOT_NO_OLD_OPS, nullptr, const_cast<char*>(srcFontPathA.getStr()), + int flags = HOT_NO_OLD_OPS; + int fontConvertFlags = 0; +#if !SUPERVERBOSE + flags |= HOT_SUPRESS_WARNINGS | HOT_SUPRESS_HINT_WARNINGS; +#else + fontConvertFlags |= HOT_CONVERT_VERBOSE; +#endif + + cbConvert(cbctx, flags, nullptr, const_cast<char*>(srcFontPathA.getStr()), const_cast<char*>(destFilePathA.getStr()), !featuresPathA.isEmpty() ? const_cast<char*>(featuresPathA.getStr()) : nullptr, !charMapPathA.isEmpty() ? const_cast<char*>(charMapPathA.getStr()) : nullptr, nullptr, - nullptr, nullptr, 0, 0, 0, 0, 0, -1, -1, 0, nullptr); + nullptr, nullptr, fontConvertFlags, 0, 0, 0, 0, -1, -1, 0, nullptr); return true; #else
