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:
@@ -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);
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user