CMakeLists.txt               |   17 +++++-----
 goo/ft_utils.cc              |   71 +++++++++++++++++++++++++++++++++++++++++++
 goo/ft_utils.h               |   25 +++++++++++++++
 poppler/CairoFontEngine.cc   |    3 +
 poppler/Form.cc              |    5 +--
 qt5/src/QPainterOutputDev.cc |    3 +
 qt6/src/QPainterOutputDev.cc |    3 +
 splash/SplashFTFontFile.cc   |    7 ++--
 8 files changed, 118 insertions(+), 16 deletions(-)

New commits:
commit d24ff1963429f409d5286632108d46d34ae3f2b1
Author: Adrian Johnson <ajohn...@redneon.com>
Date:   Wed May 11 08:32:24 2022 +0930

    Make FT support UTF-8 filenames on windows

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1cb16f75..11da7cfb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -352,20 +352,21 @@ configure_file(poppler/poppler-config.h.cmake 
${CMAKE_CURRENT_BINARY_DIR}/popple
 find_program(GPERF gperf)
 
 set(poppler_SRCS
-  goo/gbase64.cc
-  goo/gbasename.cc
-  goo/gfile.cc
-  goo/GooTimer.cc
   goo/GooString.cc
+  goo/GooTimer.cc
+  goo/ImgWriter.cc
+  goo/JpegWriter.cc
   goo/NetPBMWriter.cc
   goo/PNGWriter.cc
   goo/TiffWriter.cc
-  goo/JpegWriter.cc
-  goo/ImgWriter.cc
-  goo/gstrtod.cc
-  goo/grandom.cc
+  goo/ft_utils.cc
+  goo/gbase64.cc
+  goo/gbasename.cc
+  goo/gfile.cc
   goo/glibc.cc
   goo/glibc_strtok_r.cc
+  goo/grandom.cc
+  goo/gstrtod.cc
   fofi/FoFiBase.cc
   fofi/FoFiEncodings.cc
   fofi/FoFiTrueType.cc
diff --git a/goo/ft_utils.cc b/goo/ft_utils.cc
new file mode 100644
index 00000000..fc89302e
--- /dev/null
+++ b/goo/ft_utils.cc
@@ -0,0 +1,71 @@
+//========================================================================
+//
+// ft_util.cc
+//
+// FreeType helper functions.
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2022 Adrian Johnson <ajohn...@redneon.com>
+//
+//========================================================================
+
+#include <cstdio>
+
+#include "ft_utils.h"
+#include "gfile.h"
+
+#ifdef _WIN32
+static unsigned long ft_stream_read(FT_Stream stream, unsigned long offset, 
unsigned char *buffer, unsigned long count)
+{
+    FILE *file = (FILE *)stream->descriptor.pointer;
+    fseek(file, offset, SEEK_SET);
+    return fread(buffer, 1, count, file);
+}
+
+static void ft_stream_close(FT_Stream stream)
+{
+    FILE *file = (FILE *)stream->descriptor.pointer;
+    fclose(file);
+    delete stream;
+}
+#endif
+
+// Same as FT_New_Face() but handles UTF-8 filenames on Windows
+FT_Error ft_new_face_from_file(FT_Library library, const char *filename_utf8, 
FT_Long face_index, FT_Face *aface)
+{
+#ifdef _WIN32
+    FILE *file;
+    long size;
+
+    if (!filename_utf8)
+        return FT_Err_Invalid_Argument;
+
+    file = openFile(filename_utf8, "rb");
+    if (!file)
+        return FT_Err_Cannot_Open_Resource;
+
+    fseek(file, 0, SEEK_END);
+    size = ftell(file);
+    rewind(file);
+
+    if (size <= 0)
+        return FT_Err_Cannot_Open_Stream;
+
+    FT_StreamRec *stream = new FT_StreamRec;
+    *stream = {};
+    stream->size = size;
+    stream->read = ft_stream_read;
+    stream->close = ft_stream_close;
+    stream->descriptor.pointer = file;
+
+    FT_Open_Args args = {};
+    args.flags = FT_OPEN_STREAM;
+    args.stream = stream;
+
+    return FT_Open_Face(library, &args, face_index, aface);
+#else
+    // On POSIX, FT_New_Face mmaps font files. If not Windows, prefer 
FT_New_Face over our stdio.h based FT_Open_Face.
+    return FT_New_Face(library, filename_utf8, face_index, aface);
+#endif
+}
diff --git a/goo/ft_utils.h b/goo/ft_utils.h
new file mode 100644
index 00000000..7f4118dc
--- /dev/null
+++ b/goo/ft_utils.h
@@ -0,0 +1,25 @@
+//========================================================================
+//
+// ft_util.h
+//
+// FreeType helper functions.
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2022 Adrian Johnson <ajohn...@redneon.com>
+//
+//========================================================================
+
+#ifndef FT_UTILS_H
+#define FT_UTILS_H
+
+#include "config.h"
+#include "poppler_private_export.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+// Same as FT_New_Face() but handles UTF-8 filenames on Windows
+POPPLER_PRIVATE_EXPORT FT_Error ft_new_face_from_file(FT_Library library, 
const char *filename_utf8, FT_Long face_index, FT_Face *aface);
+
+#endif // FT_UTILS_H
diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index ddf1b557..f73b4201 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -47,6 +47,7 @@
 #include "GlobalParams.h"
 #include <fofi/FoFiTrueType.h>
 #include <fofi/FoFiType1C.h>
+#include "goo/ft_utils.h"
 #include "goo/gfile.h"
 #include "Error.h"
 #include "XRef.h"
@@ -167,7 +168,7 @@ static std::optional<FreeTypeFontFace> 
createFreeTypeFontFace(FT_Library lib, co
     FreeTypeFontFace font_face;
 
     if (font_data.empty()) {
-        FT_Error err = FT_New_Face(lib, filename.c_str(), 0, &resource->face);
+        FT_Error err = ft_new_face_from_file(lib, filename.c_str(), 0, 
&resource->face);
         if (err) {
             delete resource;
             return {};
diff --git a/poppler/Form.cc b/poppler/Form.cc
index acd52014..4a8511f6 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -45,6 +45,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <cctype>
+#include "goo/ft_utils.h"
 #include "goo/gmem.h"
 #include "goo/gfile.h"
 #include "goo/GooString.h"
@@ -2775,8 +2776,8 @@ Form::AddFontResult Form::addFontToDefaultResources(const 
std::string &filepath,
         const std::unique_ptr<FT_Library, void (*)(FT_Library *)> 
freetypeLibDeleter(&freetypeLib, [](FT_Library *l) { FT_Done_FreeType(*l); });
 
         FT_Face face;
-        if (FT_New_Face(freetypeLib, filepath.c_str(), faceIndex, &face)) {
-            error(errIO, -1, "FT_New_Face failed for %s", filepath.c_str());
+        if (ft_new_face_from_file(freetypeLib, filepath.c_str(), faceIndex, 
&face)) {
+            error(errIO, -1, "ft_new_face_from_file failed for %s", 
filepath.c_str());
             return {};
         }
         const std::unique_ptr<FT_Face, void (*)(FT_Face *)> faceDeleter(&face, 
[](FT_Face *f) { FT_Done_Face(*f); });
diff --git a/qt5/src/QPainterOutputDev.cc b/qt5/src/QPainterOutputDev.cc
index 62f12727..db3758bd 100644
--- a/qt5/src/QPainterOutputDev.cc
+++ b/qt5/src/QPainterOutputDev.cc
@@ -40,6 +40,7 @@
 
 #include <array>
 
+#include "goo/ft_utils.h"
 #include "goo/gfile.h"
 #include "GlobalParams.h"
 #include "Error.h"
@@ -552,7 +553,7 @@ void QPainterOutputDev::updateFont(GfxState *state)
             FT_Face freeTypeFace;
 
             if (fontLoc->locType != gfxFontLocEmbedded) {
-                if (FT_New_Face(m_ftLibrary, fontLoc->path.c_str(), faceIndex, 
&freeTypeFace)) {
+                if (ft_new_face_from_file(m_ftLibrary, fontLoc->path.c_str(), 
faceIndex, &freeTypeFace)) {
                     error(errSyntaxError, -1, "Couldn't create a FreeType face 
for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->c_str() : "(unnamed)");
                     return;
                 }
diff --git a/qt6/src/QPainterOutputDev.cc b/qt6/src/QPainterOutputDev.cc
index 62f12727..db3758bd 100644
--- a/qt6/src/QPainterOutputDev.cc
+++ b/qt6/src/QPainterOutputDev.cc
@@ -40,6 +40,7 @@
 
 #include <array>
 
+#include "goo/ft_utils.h"
 #include "goo/gfile.h"
 #include "GlobalParams.h"
 #include "Error.h"
@@ -552,7 +553,7 @@ void QPainterOutputDev::updateFont(GfxState *state)
             FT_Face freeTypeFace;
 
             if (fontLoc->locType != gfxFontLocEmbedded) {
-                if (FT_New_Face(m_ftLibrary, fontLoc->path.c_str(), faceIndex, 
&freeTypeFace)) {
+                if (ft_new_face_from_file(m_ftLibrary, fontLoc->path.c_str(), 
faceIndex, &freeTypeFace)) {
                     error(errSyntaxError, -1, "Couldn't create a FreeType face 
for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->c_str() : "(unnamed)");
                     return;
                 }
diff --git a/splash/SplashFTFontFile.cc b/splash/SplashFTFontFile.cc
index f9343735..cb177045 100644
--- a/splash/SplashFTFontFile.cc
+++ b/splash/SplashFTFontFile.cc
@@ -23,6 +23,7 @@
 
 #include <config.h>
 
+#include "goo/ft_utils.h"
 #include "goo/gmem.h"
 #include "goo/GooString.h"
 #include "poppler/GfxFont.h"
@@ -42,7 +43,7 @@ SplashFontFile 
*SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA, Spl
     int i;
 
     if (src->isFile) {
-        if (FT_New_Face(engineA->lib, src->fileName.c_str(), 0, &faceA)) {
+        if (ft_new_face_from_file(engineA->lib, src->fileName.c_str(), 0, 
&faceA)) {
             return nullptr;
         }
     } else {
@@ -72,7 +73,7 @@ SplashFontFile 
*SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA, Splas
     FT_Face faceA;
 
     if (src->isFile) {
-        if (FT_New_Face(engineA->lib, src->fileName.c_str(), 0, &faceA)) {
+        if (ft_new_face_from_file(engineA->lib, src->fileName.c_str(), 0, 
&faceA)) {
             return nullptr;
         }
     } else {
@@ -89,7 +90,7 @@ SplashFontFile 
*SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
     FT_Face faceA;
 
     if (src->isFile) {
-        if (FT_New_Face(engineA->lib, src->fileName.c_str(), faceIndexA, 
&faceA)) {
+        if (ft_new_face_from_file(engineA->lib, src->fileName.c_str(), 
faceIndexA, &faceA)) {
             return nullptr;
         }
     } else {

Reply via email to