diff options
author | Caolán McNamara <caolanm@redhat.com> | 2012-09-03 13:17:09 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2012-09-03 17:01:38 +0100 |
commit | 92efdaf94bc9aa463ed7c73526fbb55ec51e9ff5 (patch) | |
tree | 1fb90acc6ece98620d699e7f186f9064d25cd4de /vcl/generic | |
parent | 4b5aa7a0bef61c9f81d2f87a7cef744d27e02309 (diff) |
Resolves: #i96826# request font installation on render failure
Use packagekit interface to request font installation when
glyph fallback fails
Change-Id: Idb6f5cb6971bd156d7cac0a79e240246e9e0f973
Diffstat (limited to 'vcl/generic')
-rw-r--r-- | vcl/generic/fontmanager/fontconfig.cxx | 131 |
1 files changed, 124 insertions, 7 deletions
diff --git a/vcl/generic/fontmanager/fontconfig.cxx b/vcl/generic/fontmanager/fontconfig.cxx index a90ecaf699e3..57a17c94f335 100644 --- a/vcl/generic/fontmanager/fontconfig.cxx +++ b/vcl/generic/fontmanager/fontconfig.cxx @@ -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; } } |