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/+/138802
Tested-by: Jenkins
Reviewed-by: Tor Lillqvist <tml@collabora.com>
This commit is contained in:
Tor Lillqvist
2022-08-25 11:57:55 +02:00
parent eaf0b96ec2
commit c8d9744445
4 changed files with 86 additions and 0 deletions
+2
View File
@@ -13,6 +13,7 @@
#include <unordered_map>
#include <memory>
#include <mutex>
#include <set>
#include <string_view>
#include <boost/property_tree/ptree.hpp>
@@ -241,6 +242,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(css::uno::Reference<css::lang::XComponent> xComponent,
int nDocumentId);
+60
View File
@@ -2584,6 +2584,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(
@@ -2607,6 +2609,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)
@@ -3801,6 +3846,21 @@ 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)
sPayload += ", ";
sPayload += "\"" + std::string(f.toUtf8().getStr()) + "\"";
}
sPayload += " ] }";
pCallback(LOK_CALLBACK_FONTS_MISSING, sPayload.c_str(), pData);
pDocument->maFontsMissing.clear();
}
}
else
{
@@ -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.");
+1
View File
@@ -1464,6 +1464,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;