configure.ac | 13 +- desktop/source/lib/init.cxx | 20 +++ external/cairo/ExternalPackage_cairo.mk | 3 external/cairo/UnpackedTarball_cairo.mk | 2 external/cairo/cairo/cairo-fd-hack.patch.0 | 15 ++ external/cairo/cairo/libcairo-bundled-soname.patch.0 | 12 ++ external/fontconfig/ExternalPackage_fontconfig.mk | 16 ++ external/fontconfig/ExternalProject_fontconfig.mk | 15 ++ external/fontconfig/Module_fontconfig.mk | 1 external/fontconfig/UnpackedTarball_fontconfig.mk | 1 external/fontconfig/libfontconfig-bundled-soname.patch.0 | 11 + external/freetype/ExternalProject_freetype.mk | 2 external/freetype/UnpackedTarball_freetype.mk | 1 external/freetype/freetype-fd-hack.patch.0 | 53 ++++++++ external/harfbuzz/UnpackedTarball_harfbuzz.mk | 3 external/harfbuzz/harfbuzz-fd-hack.patch.0 | 24 ++++ vcl/source/fontsubset/sft.cxx | 23 +++ vcl/unx/generic/fontmanager/fontmanager.cxx | 90 ++++++++------- vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 13 ++ 19 files changed, 270 insertions(+), 48 deletions(-)
New commits: commit d552b4a549d614a03aa9328e017dec27bd3ff41e Author: Tor Lillqvist <t...@collabora.com> AuthorDate: Tue Sep 20 16:07:14 2022 +0300 Commit: Tor Lillqvist <t...@collabora.com> CommitDate: Thu Feb 9 13:47:02 2023 +0000 Enable opening of downloaded fonts only in ForKit in Online We want that only the ForKit process needs to have access to new font files added to a Collabora Online instance dynamically by downloading from a server. There are however many locations in the Kit process, in core and in external libraries like harfbuzz, where the code wants to open a font file. Handle this so that the ForKit process opens such a downloaded font file and doesn't close it. The file descriptor is thus inherited by Kit processes. The font file pathname passed on to other code is a fake on in the format "/:FD:/%d" where the %d is the file descriptor of the opened font file. Add checks in all places where font files are opened, look for this special pathname format, and modify the code to just dup() the already open file descriptor in that case. All this is relevant for Linux only, as Collabora Online runs on Linux. Do the above for harfbuzz, cairo, fontconfig, and freetype. In addition make sure that these libraries (except harfbuzz which needs to be a static library and freetype) when bundled, on Linux, are built as shared libraries, and won't be confused with the corresponding system libraries by making sure their sonames are different. Change-Id: Ib059cb27e1637d07bb709249abd0d984f948caa9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140714 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tor Lillqvist <t...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146341 Tested-by: Jenkins diff --git a/configure.ac b/configure.ac index 86896f3c4c80..c232686dc696 100644 --- a/configure.ac +++ b/configure.ac @@ -10823,11 +10823,18 @@ dnl =================================================================== GRAPHITE_CFLAGS_internal="-I${WORKDIR}/UnpackedTarball/graphite/include -DGRAPHITE2_STATIC" GRAPHITE_LIBS_internal="-L${WORKDIR}/LinkTarget/StaticLibrary -lgraphite" -libo_CHECK_SYSTEM_MODULE([graphite],[GRAPHITE],[graphite2 >= 0.9.3]) - HARFBUZZ_CFLAGS_internal="-I${WORKDIR}/UnpackedTarball/harfbuzz/src" HARFBUZZ_LIBS_internal="-L${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs -lharfbuzz" -libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz-icu >= 2.6.8]) +case "$_os" in + Linux) + libo_CHECK_SYSTEM_MODULE([graphite],[GRAPHITE],[graphite2 >= 0.9.3],,,TRUE) + libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz-icu >= 0.9.42],,,TRUE) + ;; + *) + libo_CHECK_SYSTEM_MODULE([graphite],[GRAPHITE],[graphite2 >= 0.9.3]) + libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz-icu >= 0.9.42]) + ;; +esac if test "$COM" = "MSC"; then # override the above GRAPHITE_LIBS="${WORKDIR}/LinkTarget/StaticLibrary/graphite.lib" diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index d0eda23e0eb8..d0c67bda098f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -26,6 +26,10 @@ #include <postmac.h> #endif +#ifdef LINUX +#include <fcntl.h> +#endif + #ifdef ANDROID #include <osl/detail/android-bootstrap.h> #endif @@ -4554,13 +4558,27 @@ static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const c else sal_detail_set_log_selector(pCurrentSalLogOverride); } +#ifdef LINUX else if (strcmp(pOption, "addfont") == 0) { + if (memcmp(pValue, "file://", 7) == 0) + pValue += 7; + + int fd = open(pValue, O_RDONLY); + if (fd == -1) + { + std::cerr << "Could not open font file '" << pValue << "': " << strerror(errno) << std::endl; + return; + } + + OUString sMagicFileName = "file:///:FD:/" + OUString::number(fd); + OutputDevice *pDevice = Application::GetDefaultDevice(); OutputDevice::ImplClearAllFontData(false); - pDevice->AddTempDevFont(OUString::fromUtf8(pValue), ""); + pDevice->AddTempDevFont(sMagicFileName, ""); OutputDevice::ImplRefreshAllFontData(false); } +#endif } static void lo_dumpState (LibreOfficeKit* pThis, const char* /* pOptions */, char** pState) diff --git a/external/cairo/ExternalPackage_cairo.mk b/external/cairo/ExternalPackage_cairo.mk index 116db8a3499d..74a46688406a 100644 --- a/external/cairo/ExternalPackage_cairo.mk +++ b/external/cairo/ExternalPackage_cairo.mk @@ -12,7 +12,8 @@ $(eval $(call gb_ExternalPackage_ExternalPackage,cairo,cairo)) $(eval $(call gb_ExternalPackage_use_external_project,cairo,cairo)) ifneq ($(DISABLE_DYNLOADING),TRUE) -$(eval $(call gb_ExternalPackage_add_file,cairo,$(LIBO_LIB_FOLDER)/libcairo.so.2,src/.libs/libcairo.so.2.1170$(CAIRO_VERSION_MICRO).0)) +$(eval $(call gb_ExternalPackage_add_file,cairo,$(LIBO_LIB_FOLDER)/libcairo-lo.so.2.1170$(CAIRO_VERSION_MICRO).0,src/.libs/libcairo-lo.so.2.1170$(CAIRO_VERSION_MICRO).0)) +$(eval $(call gb_ExternalPackage_add_file,cairo,$(LIBO_LIB_FOLDER)/libcairo-lo.so.2,src/.libs/libcairo-lo.so.2)) endif # vim: set noet sw=4 ts=4: diff --git a/external/cairo/UnpackedTarball_cairo.mk b/external/cairo/UnpackedTarball_cairo.mk index 8353adb32035..de1d9296434d 100644 --- a/external/cairo/UnpackedTarball_cairo.mk +++ b/external/cairo/UnpackedTarball_cairo.mk @@ -28,6 +28,8 @@ $(eval $(call gb_UnpackedTarball_add_patches,cairo,\ external/cairo/cairo/cairo.ofz46165.patch.1 \ external/cairo/cairo/cairo.ofz50805.patch.1 \ external/cairo/cairo/0025-libtool-pass-use-ld.patch \ + external/cairo/cairo/libcairo-bundled-soname.patch.0 \ + external/cairo/cairo/cairo-fd-hack.patch.0 \ )) ifeq ($(OS),iOS) diff --git a/external/cairo/cairo/cairo-fd-hack.patch.0 b/external/cairo/cairo/cairo-fd-hack.patch.0 new file mode 100644 index 000000000000..e5d980e94dfb --- /dev/null +++ b/external/cairo/cairo/cairo-fd-hack.patch.0 @@ -0,0 +1,15 @@ +# -*- Mode: Diff -*- +--- src/cairo-ft-font.c ++++ src/cairo-ft-font.c +@@ -737,7 +737,10 @@ + if (ret == FcResultOutOfMemory) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (ret == FcResultMatch) { +- if (access (filename, R_OK) == 0) { ++ int nFD = -1; ++ int n; ++ if ((sscanf (filename, "/:FD:/%d%n", &nFD, &n) == 1 && filename[n] == '\0') || ++ access (filename, R_OK) == 0) { + /* If FC_INDEX is not set, we just use 0 */ + ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id); + if (ret == FcResultOutOfMemory) diff --git a/external/cairo/cairo/libcairo-bundled-soname.patch.0 b/external/cairo/cairo/libcairo-bundled-soname.patch.0 new file mode 100644 index 000000000000..92aac5f753df --- /dev/null +++ b/external/cairo/cairo/libcairo-bundled-soname.patch.0 @@ -0,0 +1,12 @@ +# -*- Mode: Diff -*- +--- src/Makefile.in ++++ src/Makefile.in +@@ -2075,7 +2075,7 @@ + $(enabled_cairo_sources) \ + $(NULL) + +-libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols) ++libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols) -release lo -Wl,-soname -Wl,libcairo-lo.so.2 + libcairo_la_LIBADD = $(CAIRO_LIBS) + libcairo_la_DEPENDENCIES = $(cairo_def_dependency) + diff --git a/external/fontconfig/ExternalPackage_fontconfig.mk b/external/fontconfig/ExternalPackage_fontconfig.mk new file mode 100644 index 000000000000..7114f80d9507 --- /dev/null +++ b/external/fontconfig/ExternalPackage_fontconfig.mk @@ -0,0 +1,16 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_ExternalPackage_ExternalPackage,fontconfig,fontconfig)) + +$(eval $(call gb_ExternalPackage_use_external_project,fontconfig,fontconfig)) + +$(eval $(call gb_ExternalPackage_add_file,fontconfig,$(LIBO_LIB_FOLDER)/libfontconfig-lo.so.1.12.0,src/.libs/libfontconfig-lo.so.1.12.0)) + +# vim: set noet sw=4 ts=4: diff --git a/external/fontconfig/ExternalProject_fontconfig.mk b/external/fontconfig/ExternalProject_fontconfig.mk index 88db225f88fc..3bbecf1d672a 100644 --- a/external/fontconfig/ExternalProject_fontconfig.mk +++ b/external/fontconfig/ExternalProject_fontconfig.mk @@ -18,6 +18,9 @@ $(eval $(call gb_ExternalProject_register_targets,fontconfig,\ build \ )) +# Can't have this inside the $(call gb_ExternalProject_run as it contains commas +fontconfig_add_fonts=/usr/share/X11/fonts/Type1,/usr/share/X11/fonts/TTF,/usr/local/share/fonts + $(call gb_ExternalProject_get_state_target,fontconfig,build) : $(call gb_Trace_StartRange,fontconfig,EXTERNAL) $(call gb_ExternalProject_run,build,\ @@ -26,23 +29,31 @@ $(call gb_ExternalProject_get_state_target,fontconfig,build) : $(gb_VISIBILITY_FLAGS) \ $(if $(filter EMSCRIPTEN,$(OS)),-pthread)" \ $(if $(filter ANDROID,$(OS)),LIBS="-lm") \ - LDFLAGS="$(call gb_ExternalProject_get_link_flags,fontconfig)" \ $(if $(filter EMSCRIPTEN,$(OS)),LIBXML2_CFLAGS="$(LIBXML_CFLAGS)" LIBXML2_LIBS="$(LIBXML_LIBS)") \ $(gb_RUN_CONFIGURE) ./configure \ - --disable-shared \ --disable-silent-rules \ --with-pic \ $(if $(filter ANDROID,$(OS)),--with-arch=arm) \ --with-expat-includes=$(call gb_UnpackedTarball_get_dir,expat)/lib \ --with-expat-lib=$(gb_StaticLibrary_WORKDIR) \ $(gb_CONFIGURE_PLATFORMS) \ + $(if $(filter ANDROID,$(OS)), \ + --disable-shared \ + ) \ $(if $(filter EMSCRIPTEN,$(OS)), \ + --disable-shared \ --with-baseconfigdir=/instdir/share/fontconfig \ --with-cache-dir=/instdir/share/fontconfig/cache \ --with-add-fonts=/instdir/share/fonts \ --enable-libxml2 \ ac_cv_func_fstatfs=no ac_cv_func_fstatvfs=no \ ) \ + $(if $(filter LINUX,$(OS)), \ + --disable-static \ + --prefix=/ \ + --with-add-fonts=$(fontconfig_add_fonts) \ + --with-cache-dir=/usr/lib/fontconfig/cache \ + ) \ && $(MAKE) -C src && $(MAKE) fonts.conf \ ) $(call gb_Trace_EndRange,fontconfig,EXTERNAL) diff --git a/external/fontconfig/Module_fontconfig.mk b/external/fontconfig/Module_fontconfig.mk index 2f8f9c8f54d6..61f201d415b6 100644 --- a/external/fontconfig/Module_fontconfig.mk +++ b/external/fontconfig/Module_fontconfig.mk @@ -12,6 +12,7 @@ $(eval $(call gb_Module_Module,fontconfig)) $(eval $(call gb_Module_add_targets,fontconfig,\ ExternalProject_fontconfig \ $(if $(filter EMSCRIPTEN,$(OS)),ExternalPackage_fontconfig_data) \ + $(if $(filter LINUX,$(OS)),ExternalPackage_fontconfig) \ UnpackedTarball_fontconfig \ )) diff --git a/external/fontconfig/UnpackedTarball_fontconfig.mk b/external/fontconfig/UnpackedTarball_fontconfig.mk index f41b21cdf552..ceb87ea062ad 100644 --- a/external/fontconfig/UnpackedTarball_fontconfig.mk +++ b/external/fontconfig/UnpackedTarball_fontconfig.mk @@ -16,6 +16,7 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,fontconfig,0)) $(eval $(call gb_UnpackedTarball_add_patches,fontconfig,\ external/fontconfig/fontconfig-2.12.1.patch.1 \ external/fontconfig/ubsan.patch \ + external/fontconfig/libfontconfig-bundled-soname.patch.0 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/fontconfig/libfontconfig-bundled-soname.patch.0 b/external/fontconfig/libfontconfig-bundled-soname.patch.0 new file mode 100644 index 000000000000..390338e957e8 --- /dev/null +++ b/external/fontconfig/libfontconfig-bundled-soname.patch.0 @@ -0,0 +1,11 @@ +# -*- Mode: Diff -*- +--- src/Makefile.in ++++ src/Makefile.in +@@ -525,6 +525,6 @@ + lib_LTLIBRARIES = libfontconfig.la + libfontconfig_la_LDFLAGS = \ +- -version-info @LIBT_VERSION_INFO@ -no-undefined $(export_symbols) ++ -version-info @LIBT_VERSION_INFO@ -no-undefined $(export_symbols) -release lo -Wl,-soname -Wl,libfontconfig-lo.so.1.12.0 + + libfontconfig_la_LIBADD = $(ICONV_LIBS) $(FREETYPE_LIBS) $(LIBXML2_LIBS) $(EXPAT_LIBS) $(LTLIBINTL) + libfontconfig_la_DEPENDENCIES = $(fontconfig_def_dependency) diff --git a/external/freetype/ExternalProject_freetype.mk b/external/freetype/ExternalProject_freetype.mk index 04c11cf794b8..e9720065490c 100644 --- a/external/freetype/ExternalProject_freetype.mk +++ b/external/freetype/ExternalProject_freetype.mk @@ -28,9 +28,9 @@ $(call gb_ExternalProject_get_state_target,freetype,build) : $(gb_CONFIGURE_PLATFORMS) \ CFLAGS="$(CFLAGS) \ $(call gb_ExternalProject_get_build_flags,freetype) \ + $(call gb_ExternalProject_get_link_flags,freetype) \ $(gb_VISIBILITY_FLAGS) \ $(gb_EMSCRIPTEN_CPPFLAGS)" \ - LDFLAGS="$(call gb_ExternalProject_get_link_flags,freetype)" \ && $(MAKE) install \ && touch $@ ) $(call gb_Trace_EndRange,freetype,EXTERNAL) diff --git a/external/freetype/UnpackedTarball_freetype.mk b/external/freetype/UnpackedTarball_freetype.mk index 076edb9e3d97..5ea678f80280 100644 --- a/external/freetype/UnpackedTarball_freetype.mk +++ b/external/freetype/UnpackedTarball_freetype.mk @@ -14,6 +14,7 @@ $(eval $(call gb_UnpackedTarball_set_tarball,freetype,$(FREETYPE_TARBALL),,freet $(eval $(call gb_UnpackedTarball_add_patches,freetype,\ external/freetype/freetype-2.6.5.patch.1 \ external/freetype/ubsan.patch \ + external/freetype/freetype-fd-hack.patch.0 \ )) $(eval $(call gb_UnpackedTarball_set_patchlevel,freetype,0)) diff --git a/external/freetype/freetype-fd-hack.patch.0 b/external/freetype/freetype-fd-hack.patch.0 new file mode 100644 index 000000000000..db2bdc9e92f6 --- /dev/null +++ b/external/freetype/freetype-fd-hack.patch.0 @@ -0,0 +1,53 @@ +# -*- Mode: Diff -*- +--- src/base/ftsystem.c ++++ src/base/ftsystem.c +@@ -237,6 +237,8 @@ + const char* filepathname ) + { + FT_FILE* file; ++ int nFD; ++ int n; + + + if ( !stream ) +@@ -257,7 +257,13 @@ + stream->read = NULL; + stream->close = NULL; + +- file = ft_fopen( filepathname, "rb" ); ++ if ( sscanf( filepathname, "/:FD:/%d%n", &nFD, &n ) == 1 && filepathname[n] == '\0') ++ { ++ lseek( nFD, 0, SEEK_SET ); ++ file = fdopen( dup( nFD ), "rb" ); ++ } ++ else ++ file = ft_fopen( filepathname, "rb" ); + if ( !file ) + { + FT_ERROR(( "FT_Stream_Open:" +--- builds/unix/ftsystem.c ++++ builds/unix/ftsystem.c +@@ -249,6 +249,8 @@ + { + int file; + struct stat stat_buf; ++ int nFD; ++ int n; + + + if ( !stream ) +@@ -255,7 +255,13 @@ + return FT_THROW( Invalid_Stream_Handle ); + + /* open the file */ +- file = open( filepathname, O_RDONLY ); ++ if ( sscanf( filepathname, "/:FD:/%d%n", &nFD, &n ) == 1 && filepathname[n] == '\0') ++ { ++ lseek( nFD, 0, SEEK_SET ); ++ file = dup( nFD ); ++ } ++ else ++ file = open( filepathname, O_RDONLY ); + if ( file < 0 ) + { + FT_ERROR(( "FT_Stream_Open:" )); diff --git a/external/harfbuzz/UnpackedTarball_harfbuzz.mk b/external/harfbuzz/UnpackedTarball_harfbuzz.mk index 9bc9e326b426..37c5946a5ce4 100644 --- a/external/harfbuzz/UnpackedTarball_harfbuzz.mk +++ b/external/harfbuzz/UnpackedTarball_harfbuzz.mk @@ -16,6 +16,9 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,harfbuzz)) $(eval $(call gb_UnpackedTarball_set_patchlevel,harfbuzz,0)) $(eval $(call gb_UnpackedTarball_add_patches,harfbuzz, \ + $(if $(filter LINUX,$(OS)), \ + external/harfbuzz/harfbuzz-fd-hack.patch.0 \ + ) \ )) # vim: set noet sw=4 ts=4: diff --git a/external/harfbuzz/harfbuzz-fd-hack.patch.0 b/external/harfbuzz/harfbuzz-fd-hack.patch.0 new file mode 100644 index 000000000000..1cc5820fd49c --- /dev/null +++ b/external/harfbuzz/harfbuzz-fd-hack.patch.0 @@ -0,0 +1,24 @@ +# -*- Mode: Diff -*- +--- src/hb-blob.cc ++++ src/hb-blob.cc +@@ -737,7 +737,19 @@ + char *data = (char *) hb_malloc (allocated); + if (unlikely (!data)) return nullptr; + +- FILE *fp = fopen (file_name, "rb"); ++ FILE *fp; ++ int nFD; ++ int n; ++ if (sscanf (file_name, "/:FD:/%d%n", &nFD, &n) == 1 && file_name[n] == '\0') ++ { ++ lseek (nFD, 0, SEEK_SET); ++ fp = fdopen (dup (nFD), "rb"); ++ } ++ else ++ { ++ fp = fopen (file_name, "rb"); ++ } ++ + if (unlikely (!fp)) goto fread_fail_without_close; + + while (!feof (fp)) diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx index 6250a1ee6f06..9b9e4dfcb5b1 100644 --- a/vcl/source/fontsubset/sft.cxx +++ b/vcl/source/fontsubset/sft.cxx @@ -1075,7 +1075,18 @@ int CountTTCFonts(const char* fname) { int nFonts = 0; sal_uInt8 buffer[12]; - FILE* fd = fopen(fname, "rb"); + FILE* fd; +#ifdef LINUX + int nFD; + int n; + if (sscanf(fname, "/:FD:/%d%n", &nFD, &n) == 1 && fname[n] == '\0') + { + lseek(nFD, 0, SEEK_SET); + fd = fdopen(dup(nFD), "rb"); + } + else +#endif + fd = fopen(fname, "rb"); if( fd ) { if (fread(buffer, 1, 12, fd) == 12) { if(GetUInt32(buffer, 0) == T_ttcf ) @@ -1106,7 +1117,15 @@ SFErrCodes OpenTTFontFile(const char* fname, sal_uInt32 facenum, TrueTypeFont** goto cleanup; } - fd = open(fname, O_RDONLY); + int nFD; + int n; + if (sscanf(fname, "/:FD:/%d%n", &nFD, &n) == 1 && fname[n] == '\0') + { + lseek(nFD, 0, SEEK_SET); + fd = dup(nFD); + } + else + fd = open(fname, O_RDONLY); if (fd == -1) { ret = SFErrCodes::BadFile; diff --git a/vcl/unx/generic/fontmanager/fontmanager.cxx b/vcl/unx/generic/fontmanager/fontmanager.cxx index 6266d7646663..0d48a692e97e 100644 --- a/vcl/unx/generic/fontmanager/fontmanager.cxx +++ b/vcl/unx/generic/fontmanager/fontmanager.cxx @@ -178,25 +178,38 @@ std::vector<PrintFontManager::PrintFont> PrintFontManager::analyzeFontFile( int OString aFullPath = aDir + "/" + rFontFile; - // #i1872# reject unreadable files - if( access( aFullPath.getStr(), R_OK ) ) - return aNewFonts; - - bool bSupported = false; - if (pFormat) + bool bSupported; + bool bHack = false; + int nFD; + int n; + if (sscanf(aFullPath.getStr(), "/:FD:/%d%n", &nFD, &n) == 1 && aFullPath.getStr()[n] == '\0') { - if (!strcmp(pFormat, "TrueType") || - !strcmp(pFormat, "CFF")) - bSupported = true; + // Hack, pathname that actually means we will use a pre-opened file descriptor + bSupported = true; + bHack = true; } - if (!bSupported) + else { - OString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) ); - if( aExt.equalsIgnoreAsciiCase("ttf") - || aExt.equalsIgnoreAsciiCase("ttc") - || aExt.equalsIgnoreAsciiCase("tte") // #i33947# for Gaiji support - || aExt.equalsIgnoreAsciiCase("otf") ) // check for TTF- and PS-OpenType too - bSupported = true; + // #i1872# reject unreadable files + if( access( aFullPath.getStr(), R_OK ) ) + return aNewFonts; + + bSupported = false; + if (pFormat) + { + if (!strcmp(pFormat, "TrueType") || + !strcmp(pFormat, "CFF")) + bSupported = true; + } + if (!bSupported) + { + OString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) ); + if( aExt.equalsIgnoreAsciiCase("ttf") + || aExt.equalsIgnoreAsciiCase("ttc") + || aExt.equalsIgnoreAsciiCase("tte") // #i33947# for Gaiji support + || aExt.equalsIgnoreAsciiCase("otf") ) // check for TTF- and PS-OpenType too + bSupported = true; + } } if (bSupported) @@ -207,33 +220,36 @@ std::vector<PrintFontManager::PrintFont> PrintFontManager::analyzeFontFile( int { SAL_INFO("vcl.fonts", "ttc: " << aFullPath << " contains " << nLength << " fonts"); - sal_uInt64 fileSize = 0; - - OUString aURL; - if (osl::File::getFileURLFromSystemPath(OStringToOUString(aFullPath, osl_getThreadTextEncoding()), - aURL) == osl::File::E_None) + if (!bHack) { - osl::File aFile(aURL); - if (aFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock) == osl::File::E_None) + sal_uInt64 fileSize = 0; + + OUString aURL; + if (osl::File::getFileURLFromSystemPath(OStringToOUString(aFullPath, osl_getThreadTextEncoding()), + aURL) == osl::File::E_None) { - osl::DirectoryItem aItem; - if (osl::DirectoryItem::get(aURL, aItem) == osl::File::E_None) + osl::File aFile(aURL); + if (aFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock) == osl::File::E_None) { - osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileSize ); - if (aItem.getFileStatus(aFileStatus) == osl::File::E_None) - fileSize = aFileStatus.getFileSize(); + osl::DirectoryItem aItem; + if (osl::DirectoryItem::get(aURL, aItem) == osl::File::E_None) + { + osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileSize ); + if (aItem.getFileStatus(aFileStatus) == osl::File::E_None) + fileSize = aFileStatus.getFileSize(); + } } } - } - //Feel free to calc the exact max possible number of fonts a file - //could contain given its physical size. But this will clamp it to - //a sane starting point - //http://processingjs.nihongoresources.com/the_smallest_font/ - //https://github.com/grzegorzrolek/null-ttf - const int nMaxFontsPossible = fileSize / 528; - if (nLength > nMaxFontsPossible) - nLength = nMaxFontsPossible; + //Feel free to calc the exact max possible number of fonts a file + //could contain given its physical size. But this will clamp it to + //a sane starting point + //http://processingjs.nihongoresources.com/the_smallest_font/ + //https://github.com/grzegorzrolek/null-ttf + const int nMaxFontsPossible = fileSize / 528; + if (nLength > nMaxFontsPossible) + nLength = nMaxFontsPossible; + } for( int i = 0; i < nLength; i++ ) { diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 64fcb6bfc2bf..d3c507a28e98 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -103,7 +103,16 @@ bool FreetypeFontFile::Map() if (mnRefCount++ == 0) { const char* pFileName = maNativeFileName.getStr(); - int nFile = open( pFileName, O_RDONLY ); + int nFile; + int nFD; + int n; + if( sscanf( pFileName, "/:FD:/%d%n", &nFD, &n ) == 1 && pFileName[n] == '\0' ) + { + lseek( nFD, 0, SEEK_SET ); + nFile = dup( nFD ); + } + else + nFile = open( pFileName, O_RDONLY ); if( nFile < 0 ) { SAL_WARN("vcl.unx.freetype", "open('" << maNativeFileName << "') failed: " << strerror(errno)); @@ -126,6 +135,8 @@ bool FreetypeFontFile::Map() SAL_WARN("vcl.unx.freetype", "mmap of '" << maNativeFileName << "' failed: " << strerror(errno)); mpFileMap = nullptr; } + else + SAL_INFO("vcl.unx.freetype", "mmap'ed '" << maNativeFileName << "' successfully"); close( nFile ); }