Resolves: #i96826# request font installation on render failure

Use packagekit interface to request font installation when
glyph fallback fails

Change-Id: Idb6f5cb6971bd156d7cac0a79e240246e9e0f973
This commit is contained in:
Caolán McNamara 2012-09-03 13:17:09 +01:00
parent 4b5aa7a0be
commit 92efdaf94b
4 changed files with 128 additions and 8 deletions

View file

@ -57,7 +57,7 @@ public:
*/
explicit LanguageTag( const rtl::OUString& rLanguage, const rtl::OUString& rCountry );
explicit LanguageTag( const LanguageTag & rLanguageTag );
LanguageTag( const LanguageTag & rLanguageTag );
~LanguageTag();
LanguageTag& operator=( const LanguageTag & rLanguageTag );

View file

@ -519,6 +519,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
) \
))
$(eval $(call gb_Library_use_externals,vcl,\
dbus \
fontconfig \
freetype \
))

View file

@ -29,10 +29,17 @@
#include "fontcache.hxx"
#include "impfont.hxx"
#include "vcl/fontmanager.hxx"
#include "vcl/vclenum.hxx"
#include <vcl/fontmanager.hxx>
#include <vcl/svapp.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/vclenum.hxx>
#include <vcl/wrkwin.hxx>
#include "outfont.hxx"
#include <i18npool/languagetag.hxx>
#include <i18nutil/unicode.hxx>
#include <rtl/strbuf.hxx>
#include <unicode/uchar.h>
#include <unicode/uscript.h>
using namespace psp;
@ -75,6 +82,10 @@ using namespace psp;
#define FC_FONTFORMAT "fontformat"
#endif
#ifdef ENABLE_DBUS
#include <dbus/dbus-glib.h>
#endif
#include <cstdio>
#include <cstdarg>
@ -797,15 +808,89 @@ namespace
OString sLang = OUStringToOString(rLangTag.getLanguage(), RTL_TEXTENCODING_UTF8).toAsciiLowerCase();
OString sRegion = OUStringToOString(rLangTag.getCountry(), RTL_TEXTENCODING_UTF8).toAsciiLowerCase();
sLangAttrib = sLang + OString('-') + sRegion;
if (FcStrSetMember(pLangSet, (const FcChar8*)sLangAttrib.getStr()))
return sLangAttrib;
if (!sRegion.isEmpty())
{
sLangAttrib = sLang + OString('-') + sRegion;
if (FcStrSetMember(pLangSet, (const FcChar8*)sLangAttrib.getStr()))
return sLangAttrib;
}
if (FcStrSetMember(pLangSet, (const FcChar8*)sLang.getStr()))
return sLangAttrib;
return sLang;
return OString();
}
#ifdef ENABLE_DBUS
LanguageTag getExemplerLangTagForCodePoint(sal_uInt32 currentChar)
{
int32_t script = u_getIntPropertyValue(currentChar, UCHAR_SCRIPT);
UScriptCode eScript = static_cast<UScriptCode>(script);
OStringBuffer aBuf(unicode::getExemplerLanguageForUScriptCode(eScript));
const char* pScriptCode = uscript_getShortName(eScript);
if (pScriptCode)
aBuf.append('-').append(pScriptCode);
return LanguageTag(OStringToOUString(aBuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
}
int autoInstallFontLangSupport(const std::vector<OString> &rNewReqs, guint xid)
{
GError *error = NULL;
/* get the DBUS session connection */
DBusGConnection *session_connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if (error != NULL)
{
g_warning ("DBUS cannot connect : %s", error->message);
g_error_free (error);
return -1;
}
/* get the proxy with gnome-session-manager */
DBusGProxy *proxy = dbus_g_proxy_new_for_name(session_connection,
"org.freedesktop.PackageKit",
"/org/freedesktop/PackageKit",
"org.freedesktop.PackageKit.Modify");
if (proxy == NULL)
{
g_warning("Could not get DBUS proxy: org.freedesktop.PackageKit");
return -1;
}
gchar **fonts = (gchar**)g_malloc((rNewReqs.size() + 1) * sizeof(gchar*));
gchar **font = fonts;
for (std::vector<OString>::const_iterator aI = rNewReqs.begin(); aI != rNewReqs.end(); ++aI)
*font++ = (gchar*)aI->getStr();
*font = NULL;
gboolean res = dbus_g_proxy_call(proxy, "InstallFontconfigResources", &error,
G_TYPE_UINT, xid, /* xid */
G_TYPE_STRV, fonts, /* data */
G_TYPE_STRING, "hide-finished", /* interaction */
G_TYPE_INVALID,
G_TYPE_INVALID);
/* check the return value */
if (!res)
g_warning("InstallFontconfigResources method failed");
/* check the error value */
if (error != NULL)
{
g_warning("InstallFontconfigResources problem : %s", error->message);
g_error_free(error);
}
g_free(fonts);
g_object_unref(G_OBJECT (proxy));
return 0;
}
guint get_xid_for_dbus()
{
const Window *pTopWindow = Application::IsHeadlessModeEnabled() ? NULL : Application::GetActiveTopWindow();
const SystemEnvData* pEnvData = pTopWindow ? pTopWindow->GetSystemData() : NULL;
return pEnvData ? pEnvData->aWindow : 0;
}
#endif
}
bool PrintFontManager::Substitute( FontSelectPattern &rPattern, rtl::OUString& rMissingCodes )
@ -950,7 +1035,39 @@ bool PrintFontManager::Substitute( FontSelectPattern &rPattern, rtl::OUString& r
pRemainingCodes[ nRemainingLen++ ] = nCode;
}
}
rMissingCodes = OUString( pRemainingCodes, nRemainingLen );
OUString sStillMissing(pRemainingCodes, nRemainingLen);
#ifdef ENABLE_DBUS
guint xid = get_xid_for_dbus();
if (xid)
{
std::vector<OString> aNewRequests;
if (sStillMissing == rMissingCodes) //replaced nothing
{
//It'd be better if we could ask packagekit using the
//missing codepoints or some such rather than using
//"language" as a proxy to how fontconfig considers
//scripts to default to a given language.
for (sal_Int32 i = 0; i < nRemainingLen; ++i)
{
LanguageTag aOurTag = getExemplerLangTagForCodePoint(pRemainingCodes[i]);
OString sTag = OUStringToOString(aOurTag.getBcp47(), RTL_TEXTENCODING_UTF8);
if (m_aPreviousLangSupportRequests.find(sTag) != m_aPreviousLangSupportRequests.end())
continue;
m_aPreviousLangSupportRequests.insert(sTag);
sTag = mapToFontConfigLangTag(aOurTag);
if (!sTag.isEmpty() && m_aPreviousLangSupportRequests.find(sTag) == m_aPreviousLangSupportRequests.end())
{
OString sReq = OString(":lang=") + sTag;
aNewRequests.push_back(sReq);
m_aPreviousLangSupportRequests.insert(sTag);
}
}
}
if (!aNewRequests.empty())
autoInstallFontLangSupport(aNewRequests, xid);
}
#endif
rMissingCodes = sStillMissing;
}
}

View file

@ -353,6 +353,8 @@ class VCL_PLUGIN_PUBLIC PrintFontManager
bool readOverrideMetrics();
std::set<OString> m_aPreviousLangSupportRequests;
PrintFontManager();
~PrintFontManager();
public: