desktop/inc/lib/init.hxx | 2 desktop/source/lib/init.cxx | 62 +++++++++++++++++++++++++++ include/LibreOfficeKit/LibreOfficeKitEnums.h | 23 ++++++++++ libreofficekit/source/gtk/lokdocview.cxx | 1 4 files changed, 88 insertions(+)
New commits: commit 0d7763e1c2676bcf7ccbaf6c632ca62b7c30ba79 Author: Tor Lillqvist <t...@collabora.com> AuthorDate: Wed Aug 24 15:40:16 2022 +0300 Commit: Tor Lillqvist <t...@collabora.com> CommitDate: Thu Aug 25 13:45:46 2022 +0200 Tell LibreOfficeKit clients what fonts in a document are missing on the machine Use the OutputDevice::StartTrackingFontMappingUse() and OutputDevice::FinishTrackingFontMappingUse() functionality that was added last year. Add a new LibreOfficeKit document callback: LOK_CALLBACK_FONTS_MISSING. "Font" here means just the family name. We dont really know what style from the family is missing. Change-Id: Iec4349b5827e7d1dbdde7f8a9f8da92efde429e0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138766 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tor Lillqvist <t...@collabora.com> diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 3ef6433ebea2..baa1b682de07 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -13,6 +13,7 @@ #include <unordered_map> #include <memory> #include <mutex> +#include <set> #include <string_view> #include <boost/property_tree/ptree.hpp> @@ -240,6 +241,7 @@ namespace desktop { std::shared_ptr< LibreOfficeKitDocumentClass > m_pDocumentClass; std::map<size_t, std::shared_ptr<CallbackFlushHandler>> mpCallbackFlushHandlers; const int mnDocumentId; + std::set<OUString> maFontsMissing; explicit LibLODocument_Impl(const css::uno::Reference<css::lang::XComponent>& xComponent, int nDocumentId); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index ada68c426d61..23807a7f1403 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2590,6 +2590,8 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, aFilterOptions[3].Value <<= nUpdateDoc; */ + OutputDevice::StartTrackingFontMappingUse(); + const int nThisDocumentId = nDocumentIdCounter++; SfxViewShell::SetCurrentDocId(ViewShellDocId(nThisDocumentId)); uno::Reference<lang::XComponent> xComponent = xComponentLoader->loadComponentFromURL( @@ -2613,6 +2615,49 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, int nState = doc_getSignatureState(pDocument); pLib->mpCallback(LOK_CALLBACK_SIGNATURE_STATUS, OString::number(nState).getStr(), pLib->mpCallbackData); } + + auto aFontMappingUseData = OutputDevice::FinishTrackingFontMappingUse(); + + // Filter out font substitutions that actually aren't any substitutions, like "Liberation + // Serif" -> "Liberation Serif/Regular". If even one of the "substitutions" of a font is to + // the same font, don't count that as a missing font. + + for (std::size_t i = 0; i < aFontMappingUseData.size();) + { + // If the original font had an empty style and one of its replacement fonts has the same + // family name, we assume the font is present. The root problem here is that the code + // that collects font substitutions tends to get just empty styles for the font that is + // being substituded, as vcl::Font::GetStyleName() tents to return an empty string. + // (Italicness is instead indicated by what vcl::Font::GetItalic() returns and boldness + // by what vcl::Font::GetWeight() returns.) + if (aFontMappingUseData[i].mOriginalFont.indexOf('/') == -1) + { + bool bSubstitutedByTheSame = false; + for (const auto &j : aFontMappingUseData[i].mUsedFonts) + { + if (j.startsWith(OUStringConcatenation(aFontMappingUseData[i].mOriginalFont + "/"))) + { + bSubstitutedByTheSame = true; + break; + } + } + + if (bSubstitutedByTheSame) + aFontMappingUseData.erase(aFontMappingUseData.begin() + i); + else + i++; + } + else + { + i++; + } + } + + for (std::size_t i = 0; i < aFontMappingUseData.size(); ++i) + { + pDocument->maFontsMissing.insert(aFontMappingUseData[i].mOriginalFont); + } + return pDocument; } catch (const uno::Exception& exception) @@ -3808,6 +3853,23 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, pDocument->mpCallbackFlushHandlers[nView]->setViewId(pViewShell->GetViewShellId().get()); pViewShell->setLibreOfficeKitViewCallback(pDocument->mpCallbackFlushHandlers[nView].get()); } + + if (pDocument->maFontsMissing.size() != 0) + { + std::string sPayload = "{ \"fontsmissing\": [ "; + bool bFirst = true; + for (const auto &f : pDocument->maFontsMissing) + { + if (bFirst) + bFirst = false; + else + sPayload += ", "; + sPayload += "\"" + std::string(f.toUtf8().getStr()) + "\""; + } + sPayload += " ] }"; + pCallback(LOK_CALLBACK_FONTS_MISSING, sPayload.c_str(), pData); + pDocument->maFontsMissing.clear(); + } } else { diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h index 22577a193e52..0e86a654a464 100644 --- a/include/LibreOfficeKit/LibreOfficeKitEnums.h +++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h @@ -860,6 +860,27 @@ typedef enum * [<startColumn>, <startRow>, <endColumn>, <endRow>] */ LOK_CALLBACK_PRINT_RANGES = 56, + + /** + * Informs the LibreOfficeKit client that a font specified in the + * document is missing. + * + * This callback is emitted right after the document has been loaded. + * + * Payload example: + * { + * "fontsmissing": [ + * "Some Random Font", + * "Another Font" + * ] + * } + * + * The names are those of the font family. Sadly it is currently + * not possible to know the name of the font style that is + * missing. + * + */ + LOK_CALLBACK_FONTS_MISSING = 57, } LibreOfficeKitCallbackType; @@ -1002,6 +1023,8 @@ static inline const char* lokCallbackTypeToString(int nType) return "LOK_CALLBACK_CONTENT_CONTROL"; case LOK_CALLBACK_PRINT_RANGES: return "LOK_CALLBACK_PRINT_RANGES"; + case LOK_CALLBACK_FONTS_MISSING: + return "LOK_CALLBACK_FONTS_MISSING"; } assert(!"Unknown LibreOfficeKitCallbackType type."); diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 0c6874660aef..051970538a08 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -1465,6 +1465,7 @@ callback (gpointer pData) case LOK_COMMAND_BLOCKED: case LOK_CALLBACK_SC_FOLLOW_JUMP: case LOK_CALLBACK_PRINT_RANGES: + case LOK_CALLBACK_FONTS_MISSING: { // TODO: Implement me break;