external/afdko/extern_makeotf.patch | 29 ++++++ vcl/source/gdi/embeddedfontsafdko.cxx | 154 +++++++++++++++++++++++----------- 2 files changed, 134 insertions(+), 49 deletions(-)
New commits: commit 14cf344bd43ec7bd3569ba025ceb95dd7a69d59a Author: Caolán McNamara <[email protected]> AuthorDate: Tue Oct 28 11:27:07 2025 +0000 Commit: Miklos Vajna <[email protected]> CommitDate: Fri Oct 31 08:31:13 2025 +0100 throw exception on afdko error Change-Id: I41aee3390988d178f3a011d58589e09e6c6209a4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193087 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/external/afdko/extern_makeotf.patch b/external/afdko/extern_makeotf.patch index fd827b0f0ceb..4021d52dec45 100644 --- a/external/afdko/extern_makeotf.patch +++ b/external/afdko/extern_makeotf.patch @@ -66,6 +66,25 @@ } // [fcdb callback] Report database parsing warning. +@@ -1185,7 +1185,8 @@ + + /* Create new callback context */ + cbCtx cbNew(char *progname, char *pfbdir, char *otfdir, +- char *cmapdir, char *featdir, dnaCtx mainDnaCtx) { ++ char *cmapdir, char *featdir, dnaCtx mainDnaCtx, ++ void (*fatal)(void*)) { + static hotCallbacks template = { + NULL, /* Callback context; set after creation */ + myfatal, +@@ -1233,6 +1234,8 @@ + h->dir.cmap = cmapdir; + + h->hot.cb = template; /* Copy template */ ++ if (fatal) ++ h->hot.cb.fatal = fatal; + h->hot.cb.ctx = h; + + h->dnaCtx = mainDnaCtx; --- afdko/c/makeotf/source/file.c 2025-09-23 13:18:57.919265608 +0100 +++ afdko/c/makeotf/source/file.c 2025-09-23 13:20:04.148358137 +0100 @@ -23,7 +23,7 @@ @@ -314,6 +333,16 @@ typedef struct cbCtx_ *cbCtx; /* Define to supply Microsoft-specific function calling info, e.g. __cdecl */ +@@ -22,7 +22,8 @@ + + /* --- Basic functions --- */ + extern cbCtx cbNew(char *progname, char *pfbdir, char *otfdir, +- char *cmapdir, char *featdir, dnaCtx mainDnaCtx); ++ char *cmapdir, char *featdir, dnaCtx mainDnaCtx, ++ void (*fatal)(void*)); + extern void cbConvert(cbCtx h, int flags, char *clientVers, + char *pfbfile, char *otffile, + char *featurefile, char *hcmapfile, char *vcmapfile, @@ -80,4 +85,8 @@ #define OTHERFLAGS_VERBOSE (1 << 15) #define OTHERFLAGS_FINAL_NAMES (1 << 16) diff --git a/vcl/source/gdi/embeddedfontsafdko.cxx b/vcl/source/gdi/embeddedfontsafdko.cxx index f6fcfbfd3180..c8a8dc490a0d 100644 --- a/vcl/source/gdi/embeddedfontsafdko.cxx +++ b/vcl/source/gdi/embeddedfontsafdko.cxx @@ -65,7 +65,6 @@ static bool convertTx(txCtx h) return true; } -#endif static void suppressDebugMessagess(txCtx h) { @@ -84,6 +83,13 @@ static void suppressDebugMessagess(txCtx h) #endif } +static void txFatalCallback(txCtx h) +{ + txFree(h); + throw std::runtime_error("fatal tx error"); +} +#endif + // 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,15 +162,30 @@ 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; +} + +#if HAVE_FEATURE_AFDKO +static void mergeFontsFatalCallback(txCtx h) +{ + mergeFontsFree(h); + throw std::runtime_error("fatal mergeFonts error"); } +#endif // System afdko could be used by calling: mergefonts -cid cidfontinfo destfile [glyphaliasfile mergefontfile]+ here bool EmbeddedFontsManager::mergefonts(const OUString& cidFontInfoUrl, const OUString& destFileUrl, @@ -188,6 +222,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 +236,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 @@ -251,6 +295,8 @@ static void* cb_memory(ctlMemoryCallbacks* /*cb*/, void* old, size_t size) return malloc(size); } + +static void makeOtfFatalCallback(void*) { throw std::runtime_error("fatal tx error"); } #endif // System afdko could be used by calling: makeotf[exe] -mf fontMenuNameDB -f srcFont -o destFile -ch charMap [-ff features] @@ -289,8 +335,9 @@ bool EmbeddedFontsManager::makeotf(const OUString& srcFontUrl, const OUString& d ctlMemoryCallbacks cb_dna_memcb{ nullptr, cb_memory }; dnaCtx mainDnaCtx = dnaNew(&cb_dna_memcb, DNA_CHECK_ARGS); - cbCtx cbctx = cbNew(nullptr, const_cast<char*>(""), const_cast<char*>(""), - const_cast<char*>(""), const_cast<char*>(""), mainDnaCtx); + cbCtx cbctx + = cbNew(nullptr, const_cast<char*>(""), const_cast<char*>(""), const_cast<char*>(""), + const_cast<char*>(""), mainDnaCtx, makeOtfFatalCallback); OString fontMenuNameDBPathA(fontMenuNameDBPath.toUtf8()); OString srcFontPathA(srcFontPath.toUtf8()); @@ -304,31 +351,40 @@ bool EmbeddedFontsManager::makeotf(const OUString& srcFontUrl, const OUString& d << (!charMapPathA.isEmpty() ? " -ch "_ostr + charMapPathA : OString()) << (!featuresPathA.isEmpty() ? " -ff "_ostr + featuresPathA : OString())); - cbFCDBRead(cbctx, const_cast<char*>(fontMenuNameDBPathA.getStr())); + bool ret = true; + try + { + cbFCDBRead(cbctx, const_cast<char*>(fontMenuNameDBPathA.getStr())); - int flags = HOT_NO_OLD_OPS; - int fontConvertFlags = 0; + int flags = HOT_NO_OLD_OPS; + int fontConvertFlags = 0; #if !SUPERVERBOSE - flags |= HOT_SUPRESS_WARNINGS | HOT_SUPRESS_HINT_WARNINGS; + flags |= HOT_SUPRESS_WARNINGS | HOT_SUPRESS_HINT_WARNINGS; #else - fontConvertFlags |= HOT_CONVERT_VERBOSE; + 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, fontConvertFlags, 0, 0, 0, 0, -1, -1, 0, nullptr); + 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, fontConvertFlags, 0, 0, 0, 0, -1, -1, 0, nullptr); + } + catch (const std::exception& e) + { + SAL_WARN("vcl.fonts", "mergeFonts failure: " << e.what()); + ret = false; + } - return true; + cbFree(cbctx); #else (void)srcFontUrl; (void)destFileUrl; (void)fontMenuNameDBUrl; (void)charMapUrl; (void)featuresUrl; - return false; #endif + return ret; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
